[英]Spring Boot Integration Testing - Mocking @Service before Application Context Starts?
I have to create a integration test for a microservice X which downloads, processes and importing csv files from external sftp servers.我必须为微服务 X 创建一个集成测试,它从外部 sftp 服务器下载、处理和导入 csv 文件。 The whole process is started by a spring boot scheduler task which starts a spring batch job for processing and importing the data.
整个过程由 spring 引导调度程序任务启动,该任务启动 spring 批处理作业以处理和导入数据。 The import process is done by the spring batch writer, which is a restTemplate Repository (so it calls post requests to another microservice Y).
导入过程由 spring 批处理编写器完成,它是一个 restTemplate 存储库(因此它调用另一个微服务 Y 的发布请求)。
I already managed to mock the sftp server, putting a test file on it and the current integration test is downloading the file.我已经设法模拟了 sftp 服务器,在其上放置了一个测试文件,当前的集成测试正在下载该文件。 ( https://github.com/stefanbirkner/fake-sftp-server-rule/ )
( https://github.com/stefanbirkner/fake-sftp-server-rule/ )
My problem is, that the task will be scheduled immediately when the application context starts so there is no trigger like a api call.我的问题是,该任务将在应用程序上下文启动时立即安排,因此没有像 api 调用这样的触发器。 To get the whole integration test working i have to mock the part where the external microservice Y is called through a restTemplate call.
为了让整个集成测试正常工作,我必须模拟通过 restTemplate 调用调用外部微服务 Y 的部分。 This repository is called in the spring batch writer and this repository is created by a repositoryFactory which is a @Service.
此存储库在 spring 批处理写入器中调用,此存储库由作为 @Service 的 repositoryFactory 创建。 The repositoryFactory is injected in the spring batch configuration class.
repositoryFactory 被注入到 spring 批量配置 class 中。
I already tried to use the @MockBean annotation in the test class as well as in a separate test configuration where i am mocking the create() function of the factory to deliver a repository mock.我已经尝试在测试 class 以及在我是 mocking 的单独测试配置中使用 @MockBean 注释,创建() function 工厂的模拟文件。 But at some point it does not work and it delivers still the original object which leads to interupt the import job.
但在某些时候它不起作用,它仍然提供原始的 object,这会导致导入工作中断。
I also tried to use the WireMock library, but also in this case it does not catched any api calls and at some point leads to interrupt the sftp socket.我还尝试使用 WireMock 库,但在这种情况下,它也没有捕获任何 api 调用,并且在某些时候会导致中断 sftp 套接字。 (?)
(?)
I hope someone could help me out.我希望有人可以帮助我。
The current test:目前的测试:
@NoArgsConstructor
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = {JsonHalConfig.class})
@TestPropertySource(locations = "classpath:application-test.properties")
@TestMethodOrder(MethodOrderer.MethodName.class)
public class ImportIT {
@ClassRule
public static final FakeSftpServerRule sftpServer = new FakeSftpServerRule();
private static final String PASSWORD = "password";
private static final String USER = "username";
private static final int PORT = 14022;
@BeforeClass
public static void beforeClass() throws IOException {
URL resource = getTestResource();
if (resource != null) {
sftpServer.setPort(PORT).addUser(USER, PASSWORD);
sftpServer.createDirectories("/home/username/it-space/IMPORT", "/home/username/it-space/EXPORT");
sftpServer.putFile("/home/username/it-space/IMPORT/INBOX/testFile.csv",
resource.openStream());
} else {
throw new IOException("Failed to get test resources");
}
}
private static URL getTestResource() {
return ImportIT.class.getClassLoader().getResource("testFile.csv");
}
@Test
public void test_A_() throws IOException, RepositoryException {
assertTrue(true);
}
}
I tried following configuration classes我尝试了以下配置类
(included in @ContextConfiguration) (包含在@ContextConfiguration 中)
@Configuration/@TestConfiguration
public class RepositoryTestConfig {
@Bean
@Primary
public IRepositoryFactory repositoryFactory() {
IRepositoryFactory repositoryFactory = mock(IRepositoryFactory.class);
IRepository repository = mock(IRepository.class);
when(repositoryFactory.create(anyString())).thenReturn(repository);
return repositoryFactory;
}
}
(as static class in the test class) (作为测试类中的 static class)
@TestConfiguration/@Configuration
public static class RepositoryTestConfig {
@MockBean
private IRepositoryFactory repositoryFactory;
@PostConstruct
public void initMock(){
IRepository repository = mock(IRepository.class);
Mockito.when(repositoryFactory.create(anyString())).thenReturn(
repository
);
}
}
UPDATE 27.08.2021 I have a RestConfig @Component where a new RestTemplateBuilder is created.更新 27.08.2021我有一个 RestConfig @Component 在其中创建了一个新的 RestTemplateBuilder。 I tried to @MockBean this component to deliver a RestTemplateBuilder Mock and injected a MockRestServiceServer object to catch outgoing api calls.
我试图@MockBean 这个组件来提供一个 RestTemplateBuilder 模拟并注入一个 MockRestServiceServer object 来捕捉传出的 api 调用。 But unfortunately it does not work as aspected.
但不幸的是,它不能像方面那样工作。 Am i missing something?
我错过了什么吗? I also tried to create a "TestRestController" to trigger the scheduling of the task but it never delivers the mock...
我还尝试创建一个“TestRestController”来触发任务的调度,但它从不提供模拟......
I normally use @MockBean
directly inside my test classes and inject the dedicated (but mocked) repository directly there and not create it inside the test configuration.我通常直接在我的测试类中使用
@MockBean
,并直接在那里注入专用(但模拟的)存储库,而不是在测试配置中创建它。 I also add the test configuration class by @ContextConfiguration
so it is loaded in current test context.我还通过
@ContextConfiguration
添加了测试配置 class ,因此它被加载到当前测试上下文中。
Inside my tests I am just using mockito the standard way and prepare the mocked parts as wanted for the dedicated test method.在我的测试中,我只是以标准方式使用 mockito,并根据需要为专用测试方法准备模拟部件。
Here an example snippet:这是一个示例片段:
// ... do some imports ...
@RunWith(SpringRunner.class)
@ContextConfiguration(classes= {XYZSomeWantedClazz.class, DemoXYZMockTest.SimpleTestConfiguration.class})
@ActiveProfiles({Profiles.TEST})
public class DemoXYZMockTest {
//...
@MockBean
private DemoRepository mockedDemoRepository;
// ...
@Test
public void testMethodName() throws Exception{
/* prepare */
List<WantedEntityClazz> list = new ArrayList<>();
// add your wanted data to your list
// apply to mockito:
when(mockedDemoRepository.findAll()).thenReturn(list);
/* execute */
// ... execute the part you want to test...
/* test */
// ... test the results after execution ...
}
@TestConfiguration
@Profile(Profiles.TEST)
@EnableAutoConfiguration
public static class SimpleTestConfiguration{
// .. do stuff if necessary or just keep it empty
}
}
For a complete (old Junit4) working test example please take a look at: https://github.com/mercedes-benz/sechub/blob/3f176a8f4c00b7e8577c9e3bea847ecfc91974c3/sechub-administration/src/test/java/com/daimler/sechub/domain/administration/signup/SignupAdministrationRestControllerMockTest.java有关完整(旧 Junit4)工作测试示例,请查看: https://github.com/mercedes-benz/sechub/blob/3f176a8f4c00b7e8577c9e3bea847ecfc91974c3/sechub-administration/src/test/java/com/daimler/daimler域/管理/注册/SignupAdministrationRestControllerMockTest.java
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.