简体   繁体   中英

Mockito : Testing void methods gives InvalidUseOfMatchersException

I'm having problems with two void methods. In encouragedVenturesScoring I've followed this answer mocking an arraylist that will be looped in a for loop and haven't mocked the list, but passed a real list and added mocked objects.

Mockito gives me an InvalidUseOfMatchersException on this line

verify(effectList.get(Mockito.anyInt())).execute(playerHandler);

There are lots of questions on SO on this exception , and I think it's because of anyInt(). Anyway I changed it to

verify(effectList.get(0)).execute(playerHandler);

And now it's saying Wanted but not invoked effect.execute(playerHandler) Actually there were zero interactions with this mock

Is it because I put doNothing ? doNothing().when(effect).execute(playerHandler);


In my second method militaryStrengthScoring() method is there a way to skip the first chunk of code and just test the if..else condition? What would be the best approach to test this method?

Thank you for your time.

This is the class to be tested

 public class EndGameScoringBaseController implements EndGameScoringHandler {

private static final int[] TERRITORIES_REWARD = {0,0,1,4,10,20};
private static final int[] CHARACTERS_REWARD = {1,3,6,10,15,21};
private static final int RESOURCES_RATE = 5;
private static final int FIRST_MILITARY_REWARD = 5;
private static final int SECOND_MILITARY_REWARD = 2;

private PlayerHandler player;

public EndGameScoringBaseController(PlayerHandler player) {
    super();
    this.player = player;
}

@Override
public void encouragedVenturesScoring() {
    for (DevelopmentCard card : player.getPlayer().getPersonalBoard().getVentures()) {
        for (Effect e : card.getPermanentEffects())
            e.execute(player);
    }
}

@Override
public void militaryStrengthScoring(GameController game) {
    Set<Integer> points = new HashSet<>();
    int myPoints = this.player.getPointsHandler().getMilitaryPoints();

    for (PlayerHandler p: game.getPlayers()) {
        points.add(p.getPointsHandler().getMilitaryPoints());
    }
    int[] rank = new int[points.size()];
    int j = 0;
    for (Integer i : points) {
        rank[j] = i;
        j++;
    }

    Arrays.sort(rank);

    if (rank[rank.length-1] == myPoints) {
        player.getPointsHandler().winMilitaryPoints(FIRST_MILITARY_REWARD);
    }
    else if (rank[rank.length-2] == myPoints) {
        player.getPointsHandler().winVictoryPoints(SECOND_MILITARY_REWARD);
    }

}

Tested method for encouragedVenturesScoring

@Test
public void encouragedVenturesScoringTest() {
    //given
    List<DevelopmentCard> ventureList;
    ventureList = Arrays.asList(developmentCard, developmentCard);
    when(playerHandler.getPlayer().getPersonalBoard().getVentures()).thenReturn(ventureList);
    List<Effect> effectList;
    effectList = Arrays.asList(effect, effect);
    when(developmentCard.getPermanentEffects()).thenReturn(effectList);
    doNothing().when(effect).execute(playerHandler);

    //when
    endgameController.encouragedVenturesScoring();

    //then
    verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
}

Incomplete tested method for militaryStrengthScoring

@Test
public void militaryStrengthScoringTest() {

//given     
when(playerHandler.getPointsHandler().getMilitaryPoints()).thenReturn(4);
doNothing().when(playerHandler.getPointsHandler()).winMilitaryPoints(FIRST_MILITARY_REWARD);

//when
endgameController.militaryStrengthScoring(gameController);

//then
/../    
}

You can only verify mock objects created by Mockito.

But effectList is a "real" list. Therefore Mockito knows nothing about that object. Thus any attempt to verify that list must fail.

If you want to verify that object - then you have to mock it!

Of course, this means that you have specify all calls that will go to the mocked list.

You're right that this is the problem:

verify(effectList.get(Mockito.anyInt())).execute(playerHandler);

Mockito only allows for calls like any() and anyInt() to stand in for parameters to the mock themselves, due to the internal implementation of matchers .

/*  OK */  when(yourMock.yourMethod(anyInt())).thenReturn(42);
/* BAD */  when(yourList.get(anyInt()).yourMethod(0)).thenReturn(42);

/*  OK */  verify(yourMock).yourMethod(anyInt());
/* BAD */  verify(yourList.get(anyInt())).yourMethod(0);

The failure with get(0) is likely an actual failure, and may be related to the fact that your encouragedVenturesScoringTest is actually not calling encouragedVenturesScoring , it's calling influencedCharactersScoring . If this continues to give you trouble after fixing that error, in ways related to Mockito, please edit your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM