在Spring的构建后阶段之前注入模拟

时间:2018-10-19 14:18:36

标签: java spring unit-testing spring-boot mockito

基本上,问题在标题中。 我遇到的问题是,在构造后阶段,我的bean(现在已经自动装配到正在进行构造后阶段的bean中)已经被嘲笑了,但是Mockito.when()描述的所有行为都不起作用,所有呼叫都返回null

在搜索时,我发现了this解决方案。

但是可以在不使用任何第三方库的情况下使其运行吗?

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ContextConfiguration(classes = TestApplicationConfiguration.class)
public class ServiceTest {

@Autowired
@Qualifier("test")
private PCLPortType pclPortType;

@MockBean
private ClearingHelper сlearingHelper;

@MockBean
private OrganizationCacheRepository organizationCacheRepository;

@Before
public void setup() throws Exception{

     OperationResultWithOrganizationSystemIdMappingList res = new OperationResultWithOrganizationSystemIdMappingList();

    when(clearingHelper.getOrgIdSystemIdMapping(any(Keycloak.class))).thenReturn(res);
}


@Test
public void test() throws Exception{
    pclPortType.call("123");
}
}

测试配置:

@TestConfiguration
public class TestApplicationConfiguration {

@Bean(name = "test")
public PCLPortType pclPortTypeForTest() throws JAXBException {
   ...
}

@Bean
public Keycloak keycloak() {
    return Mockito.mock(Keycloak.class);
}
}

我要模拟豆的组件:

@Component
public class OrganizationCacheJob {
private static final Logger logger = 
LogManager.getLogger(OrganizationCacheJob.class);

private final ObjectFactory<Keycloak> factory;
private final ClearingHelper clearingHelper;
private final OrganizationCacheRepository organizationCacheRepository;

@Autowired
public OrganizationCacheJob(ObjectFactory<Keycloak> factory,
                            ClearingHelper clearingHelper,
                            OrganizationCacheRepository organizationCacheRepository) {
    this.factory = factory;
    this.clearingHelper = ClearingHelper;
    this.organizationCacheRepository = organizationCacheRepository;
}


@PostConstruct
public void updateCacheRepository() {
    doUpdateCacheRepository();
}

@Scheduled(cron = "${organization.cache.schedule}")
public void start() {
    logger.info("Starting update organization cache.");
    doUpdateCacheRepository();
    logger.info("Job finished.");
}

private void doUpdateCacheRepository() {
    try {
        Keycloak keycloak = factory.getObject();
        OperationResultWithOrganizationSystemIdMappingList orgIdSystemIdMapping = clearingHelper.getOrgIdSystemIdMapping(keycloak);
        if (orgIdSystemIdMapping != null) {
            orgIdSystemIdMapping.getContent().forEach(o -> organizationCacheRepository.saveOrgIdsSystemsIdsMappings(o.getOrgId(), o.getId()));
            logger.debug("Was saved {} orgIds", orgIdSystemIdMapping.getContent().size());
        }
    } catch (Exception e) {
        logger.error("Error fetching whole mapping for org and systems ids. Exception: {}", e);
    }
}
}

因此,在OrganizationCacheJob的构造后阶段,我想在调用res时得到clearingHelper,但我得到的是null

ClearingHelper是带有公共方法标记为@Component的常规Spring bean。

1 个答案:

答案 0 :(得分:1)

啊,好吧,我刚刚意识到-当您启动测试用例时,整个环境首先启动并运行,然后进入测试阶段。因此,根据您的情况进行分析-首先,您需要调用注入和后构造,然后完成ILogger方法,从而得到结果。

因此,正如您所看到的那样,代码比您在原始文章中可以输入的所有单词都更多。

如果可能的话,请使用模拟间谍。如果无法构建该结构,则必须重新设计测试以不依赖后期构建。

在这种情况下,由于您希望每个测试用例具有相同的构造后行为,因此请为给定的模拟提供自己的工厂方法(就像您对keycloak所做的一样),然后将when-doReturn移到那里。可以保证它将在后构造之前发生。