Mockito injection ne fonctionne pas pour le constructeur ET le setter se moque ensemble
J'ai une classe qui a des membres injecté par les constructeurs, et d'AUTRES à travers les setters. Je n'arrive pas à obtenir Mockito pour injecter le setter. Le constructeur-injectés, se moquaient bien, mais le setter celles revenir comme nulle. Lorsque j'ai présenté le setter-ed membres de constructeur - injecté, tout est bien. voici l'origine de la production de code:
@Autowired
private BetRepository betRepository;
public void setBetRepository(BetRepository betRepository) {
this.betRepository = betRepository;
}
public TournamentScoringCache(TournamentScoringCacheInitializer cacheInitializer,
ScoringEngineInitializer scoringEngineInitializer) {
tournamentUserStates = cacheInitializer.initCache();
scoringEngines = scoringEngineInitializer.initEngines();
}
public <T extends SideScore> void updateGameScore(Long tournamentId, Long gameId, MatchScore<T> score) {
Map<Long, UserTournamentState> userStates = tournamentUserStates.get(tournamentId);
ScoringEngine<?> scoringEngine = scoringEngines.get(tournamentId);
List<Bet> bets = betRepository.getBetsByGameId(gameId); //HERE IS WHERE I GET THE NPE
....
}
Code De Test:
@Mock
BetRepository betRepository;
@Mock
TournamentScoringCacheInitializer cacheInitializer;
@Mock
ScoringEngineInitializer engineInitializer;
@InjectMocks
private TournamentScoringCacheAndDB tournamentScoringCache;
@Test
public void testUpdateGameScore() {
....
when(cacheInitializer.initCache()).thenReturn(utss);
when(betRepository.getBetsByGameId(1L)).thenReturn(createBets());
when(engineInitializer.initEngines()).thenReturn(createEngines());
when(engine.getBetScore(bet1, score)).thenReturn(betScore);
when(engine.getBetScore(bet2, score)).thenReturn(betScore2);
tournamentScoringCache.updateGameScore(tournamentId, gameId, score);
....
}
Des idées?
Merci!
OriginalL'auteur Yotam Soen | 2012-10-01
Vous devez vous connecter pour publier un commentaire.
Oui, @InjectMocks annotation rend Mockito SOIT faire de constructeur d'injection, OU setter/champ d'injection, mais JAMAIS les deux. Les règles autour de laquelle seront choisis sont assez compliqués, qui est l'une des raisons pourquoi j'essaie d'éviter d'utiliser @InjectMocks chaque fois que possible.
Pour résumer, Mockito choisit d'ABORD un constructeur parmi ceux que la classe a, ENSUITE, des analyses de savoir si ce constructeur peut être utilisé pour le constructeur d'injection. Celui qu'il choisit sera toujours celui avec le plus grand nombre d'arguments. Si il y a plusieurs constructeurs avec le même nombre d'arguments, alors il n'est pas celui qui sera choisi.
Constructeur d'injection ne sera PAS utilisée si le type d'un ou plusieurs des paramètres de la CHOISI du constructeur est d'un type primitif, ou un dernier de la classe ou d'un cours privé. Même si il y a d'autres constructeurs qui POURRAIENT être utilisés.
Constructeur si l'injection n'est pas utilisé, ou si le seul constructeur est le constructeur par défaut, puis setter/champ d'injection sera utilisé à la place. Mais setter/champ d'injection n'est jamais utilisé en conjonction avec le constructeur d'injection.
Je vous recommande d'appeler explicitement la setters sur l'objet du test. Ne comptez pas sur @InjectMocks de le faire pour vous.
Oh pinaise! merci encore pour les réponses rapides!
Vous devez écrire vous-même. Bien conçu objet, vous ne pas la poursuite de l'initialisation de l'objet avec les poseurs de après l'objet a été créé avec un constructeur, c'est mauvais, en général, vous devriez toujours éviter de mutabilité, car il peut bork votre objet interne, les conteneurs, et d'autres collaborateurs.
OriginalL'auteur Dawood ibn Kareem
Bien que Constructeur d'injection est fortement recommandé, et j'avais fortement déconseillé de mélanger injection méthodes, j'ai rencontré une telle classe que je ne peux pas refactoriser. Pour contourner le problème, appeler
initMocks
explicitement. Par exemple:OriginalL'auteur Druckles
Ce qui est voulu par mockito cadre. Voir ce Github Problème.
J'ai découvert qu'il est possible de contourner ce comportement, si vous étendez votre testclass de toute autre classe (j'ai créé une classe vide avec un nom significatif et un petit commentaire).
Je ne sais pas exactement pourquoi, mais j'ai la conviction que dans le cas d'un test étendu classe toute routine interne de mockito va faire l'injection deux fois. Peut-être parce que mockito va à travers la classe hirachy et a une routine interne qui injecte à travers constructeur, sur la première fois et la deuxième fois qu'il fait le setter de la propriété de l'injection. Juste une supposition. Si j'ai le temps je vais regarder dans le mockito mise en œuvre.
OriginalL'auteur Mark Kowalski