简体   繁体   English

Spring 启动集成测试 - Mocking @Service 在应用程序上下文启动之前?

[英]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.

相关问题 测试 Spring 启动应用程序,实体模拟 - Testing Spring boot application, Entity mocking Mockito + Rest-Assured在Spring Boot REST MVC应用程序中未进行模拟(集成测试) - Mockito+ Rest-Assured not mocking in Spring Boot REST MVC application(Integration Testing) 带有集成测试的 Spring Boot 应用程序的 Jenkins 作业 - Jenkins jobs for spring boot application with Integration testing 集成测试Spring Boot应用程序JSON声明 - Integration Testing Spring boot application JSON Assert Mocking 一个 OpenFeign 客户端,用于 spring 库中的单元测试,而不是用于 spring 引导应用程序 - Mocking an OpenFeign client for Unit Testing in a spring library and NOT for a spring boot application 在 Spring Boot 服务层的单元测试中模拟原始字符串 - Mocking raw String in unit testing for Spring Boot service layer Spring Boot集成测试 - Spring Boot Integration Testing 使用Eureka服务集成测试Spring Boot服务 - Integration Testing Spring Boot service using Eureka services 在测试期间初始化应用程序上下文,不包括 spring 集成 bean - Initialize application context during testing excluding the spring integration beans Spring Boot中多战应用的集成测试 - Integration testing of multi-war application in Spring Boot
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM