2

Does mocking a method using mockito ensures that mocked method will never be called? I have Main class which contains some code i want to write unit tests for and i have one unit test class MainTest which contains unit tests for Main class.

eg:

Source Class:

package abc; public class Main { public int check1() { int num = 10; num = modify(num); return num; } public int modify(int num) { if (num % 10 == 0) return num / 10; return -1; } } 

Junit Test (using mockito)

package abc; import junit.framework.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; public class MainTest { private static Main main; @BeforeClass public static void setUp() { main = Mockito.mock(Main.class); Mockito.when(main.modify(10)).thenReturn(5); } @Test public void testCheck1() { Test1 main1 = new Main(); int num = main.check1(); Assert.assertEquals(5, num); } } 

This test is failing. Why?

0

3 Answers 3

9

EDITED Because you didn't provide a behavior for check1(). ALL methods get mocked, so without you providing a behavior, check1() returns a default value for the return type of int, which is 0. Furthermore, check1() since it is mocked does not even get to call modify().

If you are trying to test a class, you never mock the Class Under Test. On rare occasion, you might have to Spy a class under test. Rather, you mock collaborators only.

I am guessing your example was a contrived one (I hope). But if you are writing and testing a class where you think you want to modify some internal method's behavior, I see two likely probabilities:

  1. You may need to refactor the functionality of the method you want to mock-out into a collaborator class. Then it makes sense to go ahead and mock that behavior as a collaborator.
  2. You may also may need to modify the API so that you can pass in what is going to change. In your case, check1() hard-codes the value it passes to modify(), which is why you are trying to mock modify(). If instead that value were a parameter to check1() or a settable field in class Main, then there wouldn't even be a need to use a mock at all.
Sign up to request clarification or add additional context in comments.

2 Comments

Can i mock just one method of a class, not the entire class. Like just modify() in this case not check1()?
That's where the spy() (or @Spy annotation) comes into play instead of mock(). A spy will use a real instance of an object, and only override behavior where explicitly expressed by the test.
4

The Problem with your Test is, that you do not use your newly created main1 object.

If you want to change the behaviour of your systen under test (SUT) you would normally do something like this:

@Test public void testCheck1() { Test1 main1 = new Main(){ public int modify(int num) { return 5; // hard coded return value } }; int num = main1.check1(); Assert.assertEquals(5, num); } 

This creates a subclass of Main with a new implementation of the modify-method. This is an important technique for replacing hard-to-test methods in your SUT. You would normally use it to avoid expensive remote calls or similar.

It is of course possible to use a Mockito spy like this:

@Test public void testCheck1() { Test1 main1 = spy(new Main()); stub(main1.modify(10)).toReturn(5); int num = main1.check1(); Assert.assertEquals(5, num); } 

4 Comments

stub() is considered less readable than using when() according to the authors of Mockito (comments to that effect are in the Javadoc link above). But it is not deprecated, so I guess it is OK. Also, if a user already has Mockito at their disposal, then using a spy seems much clearer than declaring an inner class to partially override behavior.
I would agree using when() instead of stub() - it seems to be mainly a semantic difference.
But I prefer inner classes for modifications on my SUT because they are more flexible in most real world scenarios and have the least impact on the SUT. In short : I use mocks for the dependent Objects that I like to isolate; I use inner classes to compose the SUT to use the mocks and replace some methods.
I am quite new to Mockito, unfortunately only a few companies I worked for use unit tests or any kind of tests at all. I apologize if my question sounds silly but I wonder whats the purpose of testing a method you supply the results? It sounds to me like int a = 5; Assert.assertEquals(5, a); wont test your real method. Please advise.
0

Though i am late,it might be useful to some one. Just to add to @VivaceVivo answer: when using spies please consider doReturn|Answer|Throw() family of methods for stubbing. Sometimes it's impossible or impractical to use when(Object) for stubbing spies. more info here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.