If we only need to mock several methods of a class leaving the
rest free to respond to calls normally, we cannot mock it, we have to
spy it. Here is an example:
If we want to test myMethod, but mock the save method:
Here if we used @Mock instead of @Spy, we would see this error:
Code Coverage shows us which lines were executed:

If our method was not a void one, we would use doReturn() instead of doNothing(), rest remains the same.
We could have prepared another product instance with an id, and let the save return that instead of null as hibernate would do; but you get the idea anyway.
Note: As i just wanted to show you how to use @Spy, i intentionally did not evaluate all method results properly, as i would normally do like in this post.
Then my test would look like this:
Note 2: I will write a separate post about how to mock super class calls, since it is not readily possible with Mockito.
public class MyClass extends MyBaseClass { public void myMethod(Product p) { p.setDescription("desc"); save(p); } public void save(Product p) { super.save(p); } |
@Spy@InjectMocksprivate MyClass myClass;@Testpublic void testMyMethod() { // Preparation Product p = new Product(); doNothing().when(myClass).save(p); // Run Test myClass.myMethod(p); // Control assertEquals("desc", p.getDescription()); verify(myClass).save(p);} |
This combination of annotations is not permitted on a single field:as we cannot say “I want to mock myClass” and “I also want to test myClass, therefore inject my mocks into it” at the same time.
@Mock and @InjectMocks
Code Coverage shows us which lines were executed:

If our method was not a void one, we would use doReturn() instead of doNothing(), rest remains the same.
public Product save(Product p) {
return super.save(p);
}
@Test
public void testMyMethod() {
// Preparation
Product p = new Product();
doReturn(null).when(myClass).save(p);
}
@Testpublic void testMyMethod() { // Preparation Product p = new Product(); doReturn(null).when(myClass).save(p); ... |
Note: As i just wanted to show you how to use @Spy, i intentionally did not evaluate all method results properly, as i would normally do like in this post.
Then my test would look like this:
@RunWith(MockitoJUnitRunner.class)public class MyClassTest { @Spy @InjectMocks private MyClass myClass; @Mock private Product productMock; @Test public void testMyMethod() { // Preparation doNothing().when(myClass).save(productMock); // Run Test myClass.myMethod(productMock); // Control InOrder inOrder = Mockito.inOrder(productMock, myClass); inOrder.verify(productMock).setDescription("desc"); verifyNoMoreInteractions(productMock); inOrder.verify(myClass).save(productMock); }} |
No comments:
Post a Comment