joshskkim
joshskkim

Reputation: 65

Mocking an if condition within a for loop in JUnit

I am trying to mock a method using Mockito and JUnit. For some reason it keeps saying that the embedded method is never being invoked, despite the test fulfilling the if statement.

Here is my method that I am testing:

    public List<LifeProduct> prune(List<LifeProduct> products) {
        for (LifeProduct product : products) {
            int id = product.getProductAnalyticsIdentifier();
            boolean deleteAnnuity = id > 10014;
            boolean deleteLifeInsurance = product.getLifeInsurance()
                .getHighLevelLifeInsuranceGroupName()
                .equals("string");
            
            if (deleteAnnuity) {
                annuityService.deleteAnnuityById(id);
            }
            if (deleteLifeInsurance) {
                lifeInsuranceService.deleteLifeInsuranceById(id);
            }
        }
        
        return products;
    }

and here is my test with the iterator setup:

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
  
        when(mockList.iterator()).thenReturn(mockIterator);
        when(mockIterator.hasNext()).thenReturn(true, false);
        when(mockIterator.next()).thenReturn(mockProduct);
    }

    @Test
    public final void testPrune() throws Exception {
        for (LifeProduct mockProduct : mockList) {
            mockProduct.setProductAnalyticsIdentifier(99999999);
            doNothing().when(annuityService).deleteAnnuityById(anyInt());
            List<LifeProduct> response = lifeProductDelegate.prune(mockList);
            assertNotNull(response);
            verify(annuityService).deleteAnnuityById(anyInt());
        }
    }

Upvotes: 0

Views: 1727

Answers (1)

Tom
Tom

Reputation: 17567

Your test has two issues:

You're using the mockList and therefore use one of the two values for mockIterator.hasNext()

You say that when mockIterator.hasNext() is called, it should first return true and then false. The issue here is that your test method iterates over mockList and therefore needs to call mockIterator.hasNext() and then uses the first, the true, value. The tested method #prune() then also attempts to iterate the list, but will only get the second, the false, value, thus skipping the loop. You don't need the loop in your test method, so you can and should remove it.

You incorrectly setup mockProduct

The second issue is mockProduct.setProductAnalyticsIdentifier(99999999). mockProduct is a mock, so the methods don't do anything when not configured for example via when(mockProduct...).... So the value 99999999 is not stored anywhere and #getProductAnalyticsIdentifier() in the test returns 0, the default value. What you actually want to do is to configure the getter method, for example with:

when(mockProduct.getProductAnalyticsIdentifier()).thenReturn(999999);

Now the mockProduct will return that value when #prune() asks for the id and later compares it with 10014.

Upvotes: 2

Related Questions