11

I have a class called Availability.java and have two methods.

 public Long getStockLevelStage() {
     //some logic
      getStockLevelLimit();
    }

    public Long getStockLevelLimit() {
      String primaryOnlineArea = classificationFeatureHelper.getFirstFeatureName(productModel, FEATURE_CODE_PRODUCT_ONLINE_AREA_PRIMARY, language);
................
      return new Long();
    }

I'm writing a unit test class AvailabilityTest.java.

@RunWith(MockitoJUnitRunner.class)
public class AvailabilityTest {
  @InjectMocks
  private Availability availability = new Availability();

  @Test
  public void testGetStockLevelStage() {
    availability.getStockLevelStage();
  }
}

When I call availability.getStockLevelStage() method, it calls getStockLevelLimit() method. Is it possible to mock the internal method call?

In this case, I don't want getStockLevelLimit() to be executed, when getStockLevelStage() gets executes.

Please help.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
user2057006
  • 617
  • 4
  • 15
  • 28

2 Answers2

14

Try this:

@RunWith(MockitoJUnitRunner.class)
public class AvailabilityTest {
    @InjectMocks
    @Spy
    private Availability availability = new Availability();

    @Test
    public void testGetStockLevelStage() {
       Mockito.doReturn(expectedLong).when(availability).getStockLevelLimit();
       availability.getStockLevelStage();
    }
}

Here is an article I wrote on Mockito Spying if you need a further read.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
  • I feel donthing works for only void methods. but my getStockLevelLimit() method returns Long. Only void methods can doNothing()! Example of correct use of doNothing(): doNothing(). doThrow(new RuntimeException()) .when(mock).someVoidMethod(); Above means: someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called – user2057006 Feb 21 '17 at 16:00
  • Correct.. doReturn should be used.. sorry doing to many tests lately.. and did not pay 100% attention to the example – Maciej Kowalski Feb 21 '17 at 16:05
  • What can I do if the constructor of `Availability` calls the method I want to mock? – T3rm1 Sep 20 '18 at 09:14
10

if getStockLevelLimit() has not to be executed during your test, it means in a some way you want to mock the class under test.
Doing it reduces the relevance and the authenticity of the behavior tested.

You should mock dependencies and not internal methods of the tested class.
I suppose you don't want to execute getStockLevelLimit() because it uses external dependency that you want to isolate or something of similar.
So you should mock and isolate which is behind getStockLevelLimit() and that doesn't make directly part of the Availability class.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • if i understand correctly, we can't mock the internal method calls. Is tat right? – user2057006 Feb 21 '17 at 16:08
  • you may but you should do it only if you have no way to complete your test. A code should be designed to be naturally testable. Mocking private methods of the instance under test is all but natural. – davidxxx Feb 21 '17 at 16:12
  • I dont have option to move the getStocklevelLimit() method to another class and mock it. There is some restriction in current code which was written by another collegue. As you said there is way to do it. could you please suggest with my current code which i posted? – user2057006 Feb 21 '17 at 16:14
  • I would add that spy is appropriate for legacy code where there are just too many dependencies used and no way to refactor your code. Otherwise @davidxxx advize should be followed. – Maciej Kowalski Feb 21 '17 at 16:15
  • @Maciej- Please suggest the way using spy – user2057006 Feb 21 '17 at 16:16
  • You use spy exactly as in my answer above. This will allow for all the core implementation to be invoked and some parts like the getStockLevelLimit can be mocked if there is just too much fuzz to refactor in a timely manner. – Maciej Kowalski Feb 21 '17 at 16:19
  • @user2057006 if you want we give hints on the way to change your test, you should edit your question and show the `getStockLevelLimit()` code or at least the part he annoys you and that explains why you want to mock this private method. – davidxxx Feb 21 '17 at 16:20
  • @david There are code inside getStockLevelLimit method which will connect to hybris and fetch the stocklevel limit. Actually, I dont want to hit hybris database during test. so, i want to return any long value during test when getStockLevelLimit get executes. I updated getStockLevelLimit() method in post – user2057006 Feb 21 '17 at 16:27
  • I saw your edit. you should mock hybris processings. If you invoke them with static method you could use tools as Powermock to mock static methods otherwise you could mock the instance with classic Mockito. – davidxxx Feb 21 '17 at 16:41
  • Thanks. Its not static method. As you suggested, i ll try to mock and update here – user2057006 Feb 21 '17 at 16:52
  • 1
    Thanks david & Maciej for the response. I learnt something new after this long discussion. I will refactor the code. So, i will accept this as answers. – user2057006 Feb 21 '17 at 18:34
  • 1
    Good answer, it should mock the call outside of the class. – EM-Creations Oct 13 '17 at 10:55