Showing posts with label mocking. Show all posts
Showing posts with label mocking. Show all posts
Friday, March 19, 2010
Mockito's @InjectMocks annotation does reflection-based DI
I've been using @InjectMocks heavily lately since it came out in version 1.8.3 of mockito. The javadocs for this annotation state that it uses setter injection to inject its dependencies. Being a lazy developer, I was writing a unit test yesterday at work and forgot to write the setter methods for a couple of dependencies on the SUT that I was testing. Lo and behold, the test passed and all mock verifications were satisfied. Very confused, I went back to some other unit tests and their SUTs and removed the setter methods. In all of my cases, the tests continued to pass. A quick note to the mockito list confirms what I discovered--@InjectMocks actually is using a reflection-based DI scheme, not unlike what Spring does when you annotate collaborator fields in a Spring bean with @Autowired and @Resource. Very cool feature, as this further reduces code noise. Here is the discussion on Google Groups.
Monday, March 08, 2010
New annotations in mockito 1.8.3
Mockito 1.8.3 was recently released and I got a chance to use it today. There are a couple of new annotations available in this release: @Captor, @Spy, and @InjectMocks. I was able to use @Captor and @InjectMocks today. Even after just a few minutes with these two annotations, I'm sold. Very cool enhancement. I spent some quality time with EasyMock last week, and there's nothing easy with EasyMock. Ugh!! If you're hip to using mock objects in your Java unit testing efforts, you really should look at mockito these days. Details about @Captor and @InjectMocks follows.
This annotation will automatically create typed argument captors (
Automatically injects mocks by type using setter injection. Constructor injection is not currently available, but if you want to provide a patch, the mockito team will gladly consider your contribution. I'm actually more interested in reflection-based injection, similar to what Spring uses when annotating dependency fields using @Autowired. Having your unit tests inject dependencies via reflection would help me avoid the set* methods on the implementations. I may have to play with this a bit.
@Captor
This annotation will automatically create typed argument captors (
org.mockito.ArgumentCaptor<T>) in your unit tests. Argument captors are essential in verifying indirect outputs to your mocked collaborators.
public class Test{
@Captor ArgumentCaptor<Foobar> foobarCaptor;
@Before
public void init(){
MockitoAnnotations.init(this);
}
@Test
public void shouldDoSomethingUseful() {
//...
verify(mock.doStuff(foorbarCaptor.capture()));
Foobar capturedFoobar = foobarCaptor.getValue();
assertEquals("foobar", capturedFoobar.getName());
}
}
@InjectMocks
Automatically injects mocks by type using setter injection. Constructor injection is not currently available, but if you want to provide a patch, the mockito team will gladly consider your contribution. I'm actually more interested in reflection-based injection, similar to what Spring uses when annotating dependency fields using @Autowired. Having your unit tests inject dependencies via reflection would help me avoid the set* methods on the implementations. I may have to play with this a bit.
public class FooBarManagerTests {
@Mock private FooDependency mockFoo;
@Mock private BarDependency mockBar;
@InjectMocks private FooBarManager manager = new FooBarManagerImpl();
@Before
public void initMocks() {
// Initializes all mocks and then injects those mocks into the FooManager instance.
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldDoSomething() {
manager.doSomething();
verify(mockFoo).doSomethingToFoo(any(String.class));
verify(mockBar).doSomethingToBar(any(Integer.class));
}
}
Wednesday, November 11, 2009
Using argument matchers in EasyMock and mockito
I spent some quality time with EasyMock today while coaching some developers on building tests around an existing codebase. We were mocking a dependency of our SUT and the method call that we wanted to mock had two parameters. When we wrote the expectation, we used the anyObject() matcher for the first parameter and tried to perform an exact match on the second parameter, a Boolean. Here is an example of what we were trying to do in EasyMock (NOTE: we statically imported EasyMock so we could reduce the amount of code noise by not prefacing our expect, matcher, replay and verify invocations with EasyMock.):
Unfortunately, EasyMock and mockito do not like this. They both want you to use matchers for all parameters if you use matchers for any parameters. However, the two libraries react quite differently when this situation occurs. EasyMock complains with a somewhat confusing message that at first blush makes it seem like we declared the expectation for multiple invocations. It really threw us off for a while (at least an hour) trying to figure out what was wrong with our expectations. Here is how we fixed it in EasyMock:
Mockito does a much better job of stating that when you use a parameter argument matcher in your expectation, you have to use parameter argument matchers for all of the parameters of the method call participating in the expectation. I find it interesting that mockito retains the behavior of EasyMock (mockito is a fork of EasyMock) with regards to argument matching, but mockito improves on the error messaging when something goes wrong with the mock object setup. Further reinforces my decision to forego EasyMock in favor of mockito.
expect(mockObject.retrieveSomething((String) anyObject(), false)).andReturn(someObject);
Unfortunately, EasyMock and mockito do not like this. They both want you to use matchers for all parameters if you use matchers for any parameters. However, the two libraries react quite differently when this situation occurs. EasyMock complains with a somewhat confusing message that at first blush makes it seem like we declared the expectation for multiple invocations. It really threw us off for a while (at least an hour) trying to figure out what was wrong with our expectations. Here is how we fixed it in EasyMock:
expect(mockObject.retrieveSomething((String) anyObject(), eq(false))).andReturn(someObject);
Mockito does a much better job of stating that when you use a parameter argument matcher in your expectation, you have to use parameter argument matchers for all of the parameters of the method call participating in the expectation. I find it interesting that mockito retains the behavior of EasyMock (mockito is a fork of EasyMock) with regards to argument matching, but mockito improves on the error messaging when something goes wrong with the mock object setup. Further reinforces my decision to forego EasyMock in favor of mockito.
Thursday, November 05, 2009
Completed another Test Driven and Refactoring course for DevJam
This time using C# and the .NET platform. The course went over really well, though we did have some small snafus with the training area in the DevJam office. Nothing that can't be tweaked. I had 15 participants in this class. All participants pair programmed when completing the hand-on exercises and again, I'm totally amazed at how well pair programming goes over when you get people away from their normal work environment. Everyone really grooved on the pair programming thing.
One area that we will need to work on is the mock objects content. We don't have any hands-on exercises for using mock objects and we heard about it in the reviews of the course. I did walk everyone through a demonstration of using mock objects in your unit tests, but I mis-gauged how much interest the participants had in mock objects and the desire to get their feet wet with mock objects. Some of the class participants stay after the course ended and we did another 40 minutes of live coding demos on the use and features of mock objects (using moq for the mocking framework in .NET).
All in all, an awesome two days for me and hopefully for the course participants.
One area that we will need to work on is the mock objects content. We don't have any hands-on exercises for using mock objects and we heard about it in the reviews of the course. I did walk everyone through a demonstration of using mock objects in your unit tests, but I mis-gauged how much interest the participants had in mock objects and the desire to get their feet wet with mock objects. Some of the class participants stay after the course ended and we did another 40 minutes of live coding demos on the use and features of mock objects (using moq for the mocking framework in .NET).
All in all, an awesome two days for me and hopefully for the course participants.
Tuesday, August 18, 2009
Know your SUT and your mocks
I was working with a colleague of mine tonight and he became confused with his unit test. It was an interesting exchange, so I thought I would write it up. He had a system under test (SUT), a service, that had a number of dependencies. The dependencies were mocked using a mocking framework (mockito in this instance). He was writing a test to get better code coverage in preparation for some refactoring and he started to add an expectation to the SUT. When he ran his test, the test failed, but the error lead you to believe that it was the improper use of matchers within mockito. It took him and I awhile to realize that he was trying to add expectations to a non-mock class. In hindsight, he should have picked up on this right away, as we have a coding convention of naming our mock object instances as mock*. The SUT does not follow this naming convention and hence you should see the problem right away. A little concerned that mockito didn't alert us to the fact that we were trying to add expectations to a non-mock instance. Moral of the story: Make your mock object instances stand out--name them appropriately so everyone knows that it's a mock.
Friday, January 23, 2009
Using ArgumentMatcher to capture indirect output arguments
Yesterday, I posted a blog entry about performing assertions directly in your ArgumentMatcher implementations. I wanted to close the loop on my previous usage of the ArgumentMatcher. After some discussion with the main committer to mockito, Szczepan Faber, it seems that ArgumentMatcher should only be used to capture the indirect output argument, making it accessible to the test code. Once the test code has the indirect output argument available to it, you can then assert on it to your heart's delight. Szczepan recommended not embedding the assertions directly in the ArgumentMatcher implementation. More information can be found here. Seems like a good approach.
Subscribe to:
Posts (Atom)