Som
Som

Reputation: 1610

Mockito Junit on a reference object

I am facing a strange problem while trying to unit test my code.

Here is my code :

public class ItemService {

    private OfferService offerService;

    @Inject
    public ItemService (OfferService offerService){
        this.offerService = offerService;
    }

    public List<Item> buildItems(ItemInfo itemInfo) {
        List<Item> items = processItem(itemInfo);
        Offers<Offer> offers = fetchItemInfo(items);

        // based on the object offers, do some processing
    }


    private Offers<Offer> fetchItemInfo(List<Item> items) {
            Offers<Offer> offers = new Offers<>();
            // some processing here with offers.
            // calling the db to fetch details 
            offerService.fetchInfoFromDB(offers);
            return offers;
    }
}

public class OfferService {
    public void fetchInfoFromDB(Offers<Offer> offers) {
        // fetching details from DB
        // and updating the object **offers**
        myDao.getDetailsById(id);
    }
}

Now I have written junit to test the method buildItems()

UPDATE updating the mocks used and mock injection.

@RunWith(PowerMockRunner.class)
@PrepareForTest(ItemService.class)
public class ItemServiceTest{

    @Mock private MyDAO myDao;
    @Mock private OfferService offerService;

    @Before
    public void setUp() throws Exception {
        ItemService  itemService = new ItemService (offerService, myDao);

    }

    public void testBuildItems(){
        // some code -----
        itemInfo = buildItemInfo();
        offerDetail = buildOfferDetail();
        when(myDao.getDetailsById(Mockito.anyLong())).thenReturn(offerDetail);

        // some code -----
        // I need to implement some code which will actually call
        // offerService.fetchInfoFromDB(offers);
        // and update the --offers-- object and return it.
        List<Item> items = itemService.buildItems(itemInfo);
        Assert.assertNotNull(items);
    }
    
}

I am running with coverage and I can see that the below line got executed but the actual method is not getting called :

offerService.fetchInfoFromDB(offers);

I am getting null values in offers. Then I added the below line :

doCallRealMethod().when(offerService).fetchInfoFromDB(offers);

Still the same result. The offers object is passed by reference and is getting updated after the DB call which I am mocking already. But upto that call my code is not reaching. How can I update the offers object in my junit. Please help.

Upvotes: 1

Views: 1358

Answers (1)

Jeff Bowman
Jeff Bowman

Reputation: 95664

Your test is calling a zero arg ItemService() constructor, not the one arg @Inject constructor you posted. Either your code won't compile, or you haven't actually shown us the code in question.

Also, you say you are mocking offerService:

  1. You call when on myDao and not offerService,

  2. you do not pass your mock offerService into your ItemService constructor, as in new ItemService(offerService), and

  3. your doCallRealMethod won't work because your mock offerService won't use your mock myDao; you'll need to mock the call on offerService directly with a thenAnswer that changes the passed List<Offer>, as on my question you linked.

     doAnswer(invocation -> {
        ((List<Offer>) invocation.getArgument(0)).add(offerDetail);
        return null;
     }).when(offerService).fetchInfoFromDb(any());
    

If you fix those three you will be considerably closer to a working test.

Upvotes: 2

Related Questions