Spring, lets Mock!
How would you mock your services which are not mock-friendly?
Let’s introduce a real case (the bad one) with some preconditions:
- You have a service where DAOs are wired at runtime based on the some conditions.
- DAOs lookup API is private and not exposed to the caller
In this case you will be blocked from mocking those DAOs because of such approach.
The solution I came up with was to tweak the Spring context by unregistering the target bean (service/dao or whatever), creating the mock and registering to the context back by aliasing, to make it retrievable as regular target bean. The concept code snippet from my routine by mocking DAO’s would be:
protected <T extends IDao<?>> void mockDAO(Class<T> mockDaoClass) {
String mockedDaoClassName = mockDaoClass.getName();
GenericApplicationContext appContext = (GenericApplicationContext) applicationContext;
DefaultListableBeanFactory defaultBeanFactory = ((DefaultListableBeanFactory) appContext.getBeanFactory());
T originalDAO = (T) appContext.getBean(mockedDaoClassName);
T mockedDao = EasyMock.createNiceMock(mockDaoClass);
try {
appContext.removeBeanDefinition(mockedDaoClassName);
defaultBeanFactory.registerSingleton(mockedDaoClassName + DAO_ALIAS_ORIGINAL, originalDAO);
defaultBeanFactory.registerSingleton(mockedDaoClassName + DAO_ALIAS_MOCKED, mockedDao);
} catch (Exception e) {
fail(e.getMessage());
}
defaultBeanFactory.registerAlias(mockedDaoClassName + DAO_ALIAS_MOCKED, mockedDaoClassName);
mockedDAOGroup.add(mockedDaoClassName);
}
And after you finish, restore the bean alias to the original one:
@After
public void revertMockedDAOInAppContext() {
for (String mockedDAOClassName : mockedDAOGroup) {
GenericApplicationContext appContext = (GenericApplicationContext) applicationContext;
DefaultListableBeanFactory defaultBeanFactory = ((DefaultListableBeanFactory) appContext
.getBeanFactory());
defaultBeanFactory.registerAlias(mockedDAOClassName + DAO_ALIAS_ORIGINAL, mockedDAOClassName);
}
mockedDAOGroup.clear();
}
Yet another solution is to wrap the application context and override the #getBean operation. >> Check this out too <<.
Have a better solution?
- Login or register to post comments
- Printer-friendly version
- gadominas's blog
- 686 reads





