Mockito注入不适用于构造函数和setter模拟 [英] Mockito injection not working for constructor AND setter mocks together

查看:328
本文介绍了Mockito注入不适用于构造函数和setter模拟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,该类的成员通过构造函数注入,而其他成员则通过setter注入.我似乎无法让Mockito注入二传手.注入构造函数的方法很好,但是以setter方法返回的结果为null.当我将setter-ed成员翻转为构造函数注入时,一切都很好.这是原始的生产代码:

I have a class that has members injected through constructors, and OTHERS through setters. I can't seem to get Mockito to inject the setter ones. The constructor-injected are mocked fine, but the setter ones come back as null. When I flipped the setter-ed members to constructor- injected, all is well. here is the original production 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
....
}

测试代码:

@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);
....
}

有什么想法吗?

谢谢!

推荐答案

是的,@ InjectMocks注释使Mockito EITHER进行构造函数注入,或者进行setter/field注入,但绝不能同时进行.选择周围的规则非常复杂,这就是为什么我尽量避免使用@InjectMocks的原因之一.

Yes, the @InjectMocks annotation makes Mockito EITHER do constructor injection, OR setter/field injection, but NEVER both. The rules around which will be chosen are quite complicated, which is one reason why I try to avoid using @InjectMocks whenever possible.

总而言之,Mockito FIRST从类拥有的构造器中选择一个构造器,然后分析该构造器是否可用于构造器注入.它选择的那个永远是参数数量最多的那个.如果有多个构造函数具有相同数量的参数,那么将不确定会选择哪个.

To summarise, Mockito FIRST chooses one constructor from among those that the class has, THEN analyses whether that constructor can be used for constructor injection. The one it chooses will always be the one with the greatest number of arguments. If there are several constructors with the same number of arguments, then it is undefined which one will be chosen.

如果CHOSEN构造函数的一个或多个参数的类型是原始类型,最终类或私有类,则将不使用构造函数注入.即使可以使用其他构造函数.

Constructor injection will NOT be used if the type of one or more of the parameters of the CHOSEN constructor is a primitive type, or a final class or a private class. Even if there are other constructors that COULD be used.

如果未使用构造函数注入,或者如果唯一的构造函数是默认构造函数,则将使用setter/field注入.但是,永远不要将setter/field注入与构造函数注入结合使用.

If constructor injection is not used, or if the only constructor is the default constructor, then setter/field injection will be used instead. But setter/field injection is never used in conjunction with constructor injection.

这篇关于Mockito注入不适用于构造函数和setter模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆