1

I have the following method and I wrote a unit test in Java for this method. It is coveraged except from the if statement and I also need to test this part.

@InjectMocks
private ProductServiceImpl productService;

public void demoMethod(final List<UUID> productUuidList) {
    if (productUuidList.isEmpty()) {
        return;
    }
    final Map<ProductRequest, PriceOverride> requestMap = getPriceRequests(uuidList);
    productService.updateByPriceList(priceRequestMap, companyUuid);
}

However, as the method execution is finalized and does not return anything when uuidList is empty, I cannot test this if block.

So:

  1. How can I test this if block?

  2. Should I create a new Unit Test method for testing this if block? Or should I add related assert lines to the current test method?

Update: Here is my test method:

@Test
public void testDemoMethod() {
    final UUID uuid = UUID.randomUUID();
    final List<Price> priceList = new ArrayList<>();
    final Price price = new Price();
    
    price.setUuid(uuid);
    priceList.add(price);

    productService.demoMethod(Collections.singletonList(uuid));
}
  • 1
    what is the code you ommitted? chances are, you can test that something in that block is called 0 times, if you use a mock – Stultuske Jul 26 '21 at 13:08
  • No, it is called in this test method, there is no problem on that side. –  Jul 26 '21 at 13:17
  • @Stultuske Any idea? –  Jul 26 '21 at 13:17
  • As Stultuske wrote you could try to verify that nothing changed when you call that method with an empty list (and that it actually doesn't break) - it all depends on what the omitted code is doing. If that part cannot be tested, the only thing you could do is verify an empty list doesn't break the test. Besides that, I would create a new test method if you're explicitly testing that case. Don't mix test cases as this will be harder to track. – Thomas Jul 26 '21 at 13:18
  • @Henry did you actually understand my comment? – Stultuske Jul 26 '21 at 13:25
  • I added the test method. Any idea? –  Jul 26 '21 at 13:26
  • @Stultuske Amigo? Are you there? –  Jul 26 '21 at 13:29
  • I wasn't talking about the test method, I'm talking about the code you "omitted" in the code you are testing – Stultuske Jul 26 '21 at 13:34
  • @Stultuske Ok, I also added the other part of the `demoMethod`. I hope there is no missing part remains. –  Jul 26 '21 at 13:38
  • @Henry Can you also specify the unit testing framework you are using? JUnit? Mockito? etc? – vineetvdubey Jul 26 '21 at 13:42
  • you can mock priceService, and check that it is called 0 times – Stultuske Jul 26 '21 at 13:49
  • @Stultuske Yes, but how? Any example pls? –  Jul 26 '21 at 13:50
  • https://www.baeldung.com/mockito-series – Stultuske Jul 26 '21 at 13:51
  • Thanks a lot, actıually I already look at [this](https://www.baeldung.com/mockito-verify) page. But I am really confused and did not find a proper example. Because I need to check if there is a zero interaction if the list is empty. Any example pls? –  Jul 26 '21 at 14:31
  • `verifyNoMoreInteractions(demoService);` seems to be working, but I need to verify this based on a condition. So, how should I use this with that condition? –  Jul 26 '21 at 14:42
  • Any reply please? –  Jul 26 '21 at 17:02

3 Answers3

2

The general idea is that you don't want to test specific code, but you want to test some behaviour.

So in your case you want to verify that getPriceRequests and priceService.updateByPriceList are not called when passing in an empty List.

How exactly you do that depends on what tools you have available. The easiest way is if you already mock priceService: then just instruct your mocking liberary/framework to verify that updateByPriceList is never called.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • Yes, I mocked `priceService` but as I am really beginner for Unit Test, I have really no idea how can I verify that `updateByPriceList` is never called. Any example code pls? –  Jul 26 '21 at 13:45
  • You seem to be using Mockito. [This question talks how to verify a method is never called.](https://stackoverflow.com/questions/12862659/how-to-verify-that-a-specific-method-was-not-called-using-mockito). – Joachim Sauer Jul 26 '21 at 13:50
  • Thanks a lot, actıually I already look at [this](https://www.baeldung.com/mockito-verify) page. But I am really confused and did not find a proper example. Because I need to check if there is a zero interaction if the list is empty. Any example pls? –  Jul 26 '21 at 14:31
  • @Henry: then re-read the accepted answer, it tells you **exactly** the code to verify a method is never called. If you have a *specific* question about that, then someone can help, but just repeating "I need a sample" is not going to help. – Joachim Sauer Jul 26 '21 at 14:33
  • Accepted answer is for a previous version. I tried `verify(demoService.demoMethod(null), never()).clear()` but not working. Any idea? –  Jul 26 '21 at 14:37
  • You need to learn to be more precise with your statements. "but not working" is almost worthless as far as a problem description goes. – Joachim Sauer Jul 26 '21 at 14:38
  • `verifyNoMoreInteractions(demoService);` seems to be working, but I need to verify this based on a condition. So, how should I use this with that condition? –  Jul 26 '21 at 14:40
  • @Henry: the call with an empty list should be its own test method anyway, shouldn't it? If it isn't, you can just put that call into an `if`: unit tests are just normal Java code after all. Edit: actually: you don't want to verify that there are no more interactions with `demoService`! You want to check for `priceService`! – Joachim Sauer Jul 26 '21 at 14:42
  • The point you missed is using `@Spy` rather than `@Mock` –  Jul 27 '21 at 11:07
0

The point of doing a return in your if condition is that the rest of the code is not executed. I.e., if this // code omitted for brevity was to be executed, the method would not fill it's purpose. Therefore, just make sure that whatever that code does, it was not done if your list is empty.

PBeaumont
  • 11
  • 5
  • Thanks for reply. Yes, if the list is empty the next lines of code are not executed. So, how should I test this if block? Any example code pls for the test method? –  Jul 26 '21 at 13:40
  • Any reply please? –  Jul 26 '21 at 17:02
0

You have 3 choices:

  1. Write a unit test with mocks. Mockito allows you to verify() whether some method was invoked.
  2. Write a more high-level test with database. When testing Service Facade Layer this is usually a wiser choice. In this case you can obtain the resulting state of DB in your test to check whether it did what it had to.
  3. Refactor your code to work differently

Check out Test Pyramid and How anemic architecture spoils your tests for more details.

Stanislav Bashkyrtsev
  • 14,470
  • 7
  • 42
  • 45
  • Accepted answer is for a previous version. I tried `verify(demoService.demoMethod(null), never()).clear()` but not working. Any idea? –  Jul 26 '21 at 14:38
  • @Henry, Did you mean to write something like `verify(priceService, never()).updateByPriceList(anyObject(), anyObject())`? – Stanislav Bashkyrtsev Jul 26 '21 at 14:41
  • Actually I have no idea as I have no prior experience. ı just want to see an example usage to check zero interaction based on a condition (if a list is empty). –  Jul 26 '21 at 14:43
  • On the other hand, `verifyNoMoreInteractions(demoService);` seems to be working, but I need to verify this based on a condition. So, how should I use this with that condition? –  Jul 26 '21 at 14:44
  • @Henry, you shouldn't verify this based on a condition. Ideally tests should be free of conditions. You'd better write 2 separate tests. – Stanislav Bashkyrtsev Jul 26 '21 at 14:46
  • But `verifyNoMoreInteractions(demoService.demoMethod(null))` does not work. So, how can I test that interaction against null parameter? –  Jul 26 '21 at 14:54
  • Any reply please? –  Jul 26 '21 at 17:02