java - 在 Spring 的构建后阶段之前注入(inject) mock

标签 java spring unit-testing spring-boot mockito

基本上,问题就在标题中。
我遇到了一个问题,在构建后阶段,我的 bean(即在现在正在经历构建后阶段的 bean 中 Autowiring )已经被模拟,但是 Mockito.when() 描述的所有行为不起作用,所有调用都返回 null .

搜索时发现 this解决方案。

但是是否有可能在不使用任何 3rd 方库的情况下使其工作?

测试类:

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

我想获取模拟 bean 的组件:
@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是一个常规 Spring bean,标记为 @Component使用公共(public)方法。

最佳答案

啊,好吧,我刚刚意识到-当您开始测试用例时,整个环境首先启动并运行,然后您进入测试阶段。所以,翻译成你的案例 - 首先你调用了注入(inject)和后构造,然后 @Before方法完成,因此结果。

如您所见,代码比您在原始帖子中可以输入的所有单词都多。

如果可能的话,请使用 spy 而不是模拟。如果无法构建它,您将不得不重新设计测试以不依赖后期构建。

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

关于java - 在 Spring 的构建后阶段之前注入(inject) mock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52894254/

相关文章:

c++ - C++ 中的单元测试

java - 如何从 SQL 查询中提取列名作为字符串 SQL 查询作为字符串传递

java - 与 glassfish 为多个 web 项目共享 ejb 3

java - 如何将百分比变量的格式设置为两位小数?

java - Spring 注解: How to create autowire annotation for static/non static method with arguments

node.js - NodeJS mockgoose 保存模型似乎不起作用

java - 任何已检查异常(异常除外)与异常中的行为差异

java - spring 事务期间 autocommit=true

java - 该页面没有正确重定向 Spring Security

Android 单元测试 - 代码引用 android 类时的最佳实践