martes, octubre 25, 2011

Soy el rey de la mar tiburón Que te come a besos Pero yo soy el rey del mar tiburón El que te come mi amor (El Rey Tiburón - Maná))

Today I was googling about mocking when I have found next question:

"Injecting mock beans into spring context for testing. What I want to be able to do is via the HotswappableTargetSource override the bean definitions of select beans in my application context with my test versions and then run the test.
Then for each test case I'd like to specify which beans I want to be hot swappable and then each test must be able to create its own mock versions and swap those in, and be able to swap back again."

And there you can find a solution using ProxyFactoryBean and HotSwappableTargetSource. Well it is a solution for me a bit complicated, if I should do the same I would do using StaticApplicationContext class, because from my point of view, environment is more controlled and easy to understand. Of course the easiest solution is using Spring 3.1 Profile feature, but meanwhile it is a milestone/RC or simply because you will not be able to change Spring version, I will show you how to use StaticApplicationContext and how to inject mocked beans.

StaticApplicationContext is an implementation of ApplicationContext interface which supports programmatic registration of beans and messages, rather than reading bean definitions from external configuration sources. StaticApplicationContext has been created mainly for testing purpose. To solve the problem  we focus, some of registered beans will be the "real" beans, but others will be mocked beans with all their interactions.

For this example Mockito has been used. Let's see some code.

Imagine you have an application that should create users into a database. I suppose we would have a UserDao class for communicating with database and a UserService class to aggregate user operations. Moreover UserService class would not be alone, would be used in several modules; in fact all modules that requires user information.

Now it is time for testing. Unit test is simple, when you want to test UserService you set a mock of UserDao. Here no problem with Spring because it has not started to play yet.

But when you want to test whole system, may be you want that low-level classes like UserDao be mocked and also you want to run tests with Spring capabilities (for example developed BeanPostProcessors, Messaging, Spring AOP, ...). For solving this case you can create a test Spring context file, then you can create required mocks and set them manually. But as you can suppose another approach is using StaticApplicationContext.

The most important line is number 12 where we are injecting UserDao mock into Spring context. See that at line 11 we are also registering autowired annotation post processor. If  it was not registered, classes annotated with @Autowired would not work.

In current post I have explained how to inject mock beans into Spring Context for testing. Personally I don't like mixing mock beans with real beans in integration tests, I prefer only real beans in this kind of tests; but I can understand that in big modules where a system has multiple subsystems can be useful to isolate some modules from test. 

For example in my department we are developing clinical instruments which as you can imagine contains complex modules all related between them. When we are running some integration test, we are not available to connect to device, so communication module could be mocked. But in our case we are running integration tests with an emulator, but mocking some parts of our system could be another solution.

The example in this case is so simple I know, but in more complex scenarios you can create an application context referencing to real beans and passing it to StaticApplicationContext constructor so in static application context you only register mock beans.

This this would look:

Well now I have showed you how to register mock beans into a Spring Application Context using StaticApplicationContext instead of using HotSwappableTargetSource

Thank you very much for reading my blog.

Download Code.


3 comentarios:

kernelmanz's blog dijo...


very interesting article and very useful.


Alex dijo...

Thank you very much for your comment, only use this approach with caution because if you use in many situations can be a symptom of high coupling.


Unknown dijo...

Thank you for the information you provide, it helped me a lot! it's great that I known this site! Can you sharing some updates on how you have made this powerful post!
fb login

Donate If You Can and Find Post Useful