【问题标题】:@MockBean-instance used via @Autowire before method injection在方法注入之前通过@Autowire 使用@MockBean-instance
【发布时间】:2020-06-19 09:48:16
【问题描述】:

在我的 JUNIT5 测试中,我想通过 @MockBean 模拟一个 bean。在我的 @BeforeEach - 方法中,调用被注入。 但是其他bean @Autowire-ing @MockBean 在方法注入之前用@MockBean 实例化。这很奇怪,给了我 NPE。如何在使用 @MockBean 之前强制方法注入?

@SpringBootTest
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:context/authenticationStaff.xml")
@EnableAutoConfiguration
public class PasswordPolicyServiceTest {

    private final List<Reference> bcryptDigestRefs = new ArrayList<>();
    private final DigestHistoryRule bcryptDigestRule = new DigestHistoryRule(new BCryptHashBean());
    @MockBean
    private SystemConfiguration systemConfiguration; 

    @BeforeEach
    public void initMock() {
        MockitoAnnotations.initMocks(this);
        Arrays.asList(SystemConfigKey.values()).forEach(key -> {
            Mockito.when(systemConfiguration.getConfig(key)).thenReturn(getConfig(key, key.getDefaultValue()));
        });
        Mockito.when(systemConfiguration.getConfig(SystemConfigKey.MIN_PASSWORD_LENGTH)).thenReturn(getConfig(SystemConfigKey.MIN_PASSWORD_LENGTH, "5"));

失败的课程是:

@Service
public class SessionCacheManager {


    private final Ehcache ehCache;

    private final Cache<String, SessionVerificationType> sessionCache;

    private final SystemConfiguration systemConfiguration;

    @Autowired
    public SessionCacheManager(final Ehcache ehCache, final SystemConfiguration systemConfiguration) {
        this.ehCache=ehCache;
        this.systemConfiguration=systemConfiguration;
        SystemConfigType systemConfig = systemConfiguration.getConfig(SystemConfigKey.SESSION_MAX_NUMBER);
        Integer numberOfParalledSessions = systemConfig.getIntegerValue();
        CacheManager cacheManager=ehCache.registerNewCacheManager(CACHE_MANAGER);
        sessionCache = cacheManager.createCache(CACHE_NAME, 
                CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, SessionVerificationType.class, ResourcePoolsBuilder.heap(numberOfParalledSessions)));
    }

正如我所见(通过调试),“SessionCacheManager”使用模拟的“SystemConfiguration”,但 systemConfiguration.getConfig(SystemConfigKey.SESSION_MAX_NUMBER);返回一个空值。

【问题讨论】:

    标签: spring-boot mockito junit5


    【解决方案1】:

    我帮助了自己,虽然我不喜欢我的解决方案。这更像是一个技巧而不是一个解决方案。但我现在想不出别的。

    我将@ContextConfiguration 更改为:

    @ContextConfiguration(locations = "/context/authenticationStaff.xml", classes = { SpringApplicationContext.class })
    

    已设置 XML,它无法自动检测类“SystemConfiguration.class”。 而不是“SpringApplicationContext.class”提供“SystemConfiguration.class”作为模拟 bean。

    @Configuration
    public class SpringApplicationContext {
    
        @Mock
        private SystemConfiguration mockedSystemConfiguration;
    
        @Bean
        public SystemConfiguration systemConfiguration() {
            MockitoAnnotations.initMocks(this);
            Arrays.asList(SystemConfigKey.values()).forEach(key -> {
                Mockito.when(mockedSystemConfiguration.getConfig(key)).thenReturn(getConfig(key, key.getDefaultValue()));
            });
            Mockito.when(mockedSystemConfiguration.getConfig(SystemConfigKey.MIN_PASSWORD_LENGTH)).thenReturn(getConfig(SystemConfigKey.MIN_PASSWORD_LENGTH, "5"));
            Mockito.when(mockedSystemConfiguration.getConfig(SystemConfigKey.PASSWORD_BCRYPTENCODER_COSTFACTOR)).thenReturn(getConfig(SystemConfigKey.PASSWORD_BCRYPTENCODER_COSTFACTOR, "5"));
            return mockedSystemConfiguration;
        }
    
        private SystemConfigType getConfig(SystemConfigKey key, String value) {
            SystemConfigType config = new SystemConfigType();
            config.setKey(key);
            config.setValue(value); 
            return config;
        }
    

    测试代码现在看起来像这样:

    @SpringBootTest
    @ExtendWith(SpringExtension.class)
    @ContextConfiguration(locations = "/context/authenticationStaff.xml", classes = { SpringApplicationContext.class })
    @EnableAutoConfiguration
    public class PasswordPolicyServiceTest {
    
        @Autowired 
        private PasswordPolicyService passwordPolicyService;
        @Autowired 
        private PasswordHandlerService passwordHandlerService;
        @Autowired
        private SystemConfiguration systemConfiguration;
    
        private final List<Reference> bcryptDigestRefs = new ArrayList<>();
    
        private final DigestHistoryRule bcryptDigestRule = new DigestHistoryRule(new BCryptHashBean());
    
        @BeforeEach
        public void initMock() {
            MockitoAnnotations.initMocks(this);
            String password=passwordHandlerService.getPassword("my$Password");
            bcryptDigestRefs.add(
                    new HistoricalReference(
                            "bcrypt-history",
                            password));
        }
    

    这可行,但不是一个好的解决方案。非常欢迎其他建议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 2015-04-25
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多