@ MockBean-экземпляр, используемый через @Autowire до внедрения метода - PullRequest
0 голосов
/ 06 марта 2020

В моем тесте JUNIT5 я хочу смоделировать бин с помощью @MockBean. В моем методе @BeforeEach вызовы вводятся. Но другие бины @ 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); возвращает ноль

1 Ответ

0 голосов
/ 06 марта 2020

Я помог себе, хотя мне не нравится мое решение. Это скорее уловка, чем решение. Но сейчас я не могу думать о чем-то другом.

Я изменяю @ContextConfiguration на:

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

XML настроен, так как он не может автоматически определять класс "SystemConfiguration.class" , Вместо этого SpringApplicationContext.class предоставляет «SystemConfiguration.class» как смоделированный компонент.

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

Это работает , но это не хорошее решение. Другие рекомендации очень приветствуются.

...