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

Ник*_*лов 5 java spring unit-testing mockito spring-boot

基本上,问题就在标题中。\n我遇到一个问题,在构建后阶段我的bean(在现在正在经历构建后阶段的bean中自动装配)已经被嘲笑,但是所描述的所有行为都Mockito.when()不起作用,所有调用返回null

\n\n

在搜索时我找到了这个解决方案。

\n\n

但是是否可以在不使用任何第三方库的情况下使其工作?

\n\n

测试类:

\n\n
@RunWith(SpringRunner.class)\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)\n@ContextConfiguration(classes = TestApplicationConfiguration.class)\npublic class ServiceTest {\n\n@Autowired\n@Qualifier("test")\nprivate PCLPortType pclPortType;\n\n@MockBean\nprivate ClearingHelper \xd1\x81learingHelper;\n\n@MockBean\nprivate OrganizationCacheRepository organizationCacheRepository;\n\n@Before\npublic void setup() throws Exception{\n\n     OperationResultWithOrganizationSystemIdMappingList res = new OperationResultWithOrganizationSystemIdMappingList();\n\n    when(clearingHelper.getOrgIdSystemIdMapping(any(Keycloak.class))).thenReturn(res);\n}\n\n\n@Test\npublic void test() throws Exception{\n    pclPortType.call("123");\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

测试配置:

\n\n
@TestConfiguration\npublic class TestApplicationConfiguration {\n\n@Bean(name = "test")\npublic PCLPortType pclPortTypeForTest() throws JAXBException {\n   ...\n}\n\n@Bean\npublic Keycloak keycloak() {\n    return Mockito.mock(Keycloak.class);\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想要获取模拟 bean 的组件:

\n\n
@Component\npublic class OrganizationCacheJob {\nprivate static final Logger logger = \nLogManager.getLogger(OrganizationCacheJob.class);\n\nprivate final ObjectFactory<Keycloak> factory;\nprivate final ClearingHelper clearingHelper;\nprivate final OrganizationCacheRepository organizationCacheRepository;\n\n@Autowired\npublic OrganizationCacheJob(ObjectFactory<Keycloak> factory,\n                            ClearingHelper clearingHelper,\n                            OrganizationCacheRepository organizationCacheRepository) {\n    this.factory = factory;\n    this.clearingHelper = ClearingHelper;\n    this.organizationCacheRepository = organizationCacheRepository;\n}\n\n\n@PostConstruct\npublic void updateCacheRepository() {\n    doUpdateCacheRepository();\n}\n\n@Scheduled(cron = "${organization.cache.schedule}")\npublic void start() {\n    logger.info("Starting update organization cache.");\n    doUpdateCacheRepository();\n    logger.info("Job finished.");\n}\n\nprivate void doUpdateCacheRepository() {\n    try {\n        Keycloak keycloak = factory.getObject();\n        OperationResultWithOrganizationSystemIdMappingList orgIdSystemIdMapping = clearingHelper.getOrgIdSystemIdMapping(keycloak);\n        if (orgIdSystemIdMapping != null) {\n            orgIdSystemIdMapping.getContent().forEach(o -> organizationCacheRepository.saveOrgIdsSystemsIdsMappings(o.getOrgId(), o.getId()));\n            logger.debug("Was saved {} orgIds", orgIdSystemIdMapping.getContent().size());\n        }\n    } catch (Exception e) {\n        logger.error("Error fetching whole mapping for org and systems ids. Exception: {}", e);\n    }\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,在构建后阶段,我想在调用时OrganizationCacheJob得到,但我得到的是。resclearingHelpernull

\n\n

ClearingHelper是一个常规的 Spring bean,标记为@Component具有公共方法。

\n

Ant*_*sss 2

啊,好吧,我刚刚意识到 - 当您开始测试用例时,整个环境首先启动并运行,然后您进入测试阶段。因此,转换为您的情况 - 首先调用注入和后构造,然后@Before完成方法,从而得到结果。

正如您所看到的,代码所表达的内容比您在原始帖子中可以放入的所有文字还要多。

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

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