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



我必须为从外部sftp服务器下载、处理和导入csv文件的微服务X创建一个集成测试。整个过程由一个spring启动调度器任务启动,该任务启动一个spring批处理作业来处理和导入数据。导入过程由spring批处理编写器完成,它是一个restTemplate Repository(因此它调用对另一个微服务Y的post请求)。

我已经成功地模拟了sftp服务器,把一个测试文件放在上面,当前的集成测试正在下载该文件。(https://github.com/stefanbirkner/fake-sftp-server-rule/)

我的问题是,当应用程序上下文启动时,任务将立即被调度,因此没有像api调用这样的触发器。为了让整个集成测试工作,我必须模拟外部微服务Y通过restTemplate调用调用的部分。这个存储库在spring批处理编写器中被调用,并且这个存储库是由一个@Service的repositoryFactory创建的。repositoryFactory被注入到spring批处理配置类中。

我已经尝试在测试类中以及在一个单独的测试配置中使用@MockBean注释,其中我正在模拟工厂的create()函数以交付存储库模拟。但在某些情况下,它不工作,它仍然传递原始对象,这导致中断导入作业。

我也尝试使用WireMock库,但在这种情况下,它没有捕获任何api调用,并在某些时候导致中断sftp套接字。(?)

我希望有人能帮帮我。

当前测试:

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

我尝试了以下配置类

(包含在@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;
}
}

(作为测试类中的静态类)

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

更新27.08.2021我有一个RestConfig @Component,其中创建了一个新的RestTemplateBuilder。我尝试@MockBean这个组件来交付一个RestTemplateBuilder Mock,并注入一个MockRestServiceServer对象来捕获传出的api调用。但不幸的是,它并没有发挥作用。我错过什么了吗?我还尝试创建一个"TestRestController"触发任务的调度,但它从不交付mock…

我通常在我的测试类中直接使用@MockBean,并直接在那里注入专用(但模拟)存储库,而不是在测试配置中创建它。我还通过@ContextConfiguration添加了测试配置类,以便在当前测试上下文中加载它。

在我的测试中,我只是使用标准方式模拟,并根据需要为专用测试方法准备模拟部件。

下面是一个示例代码片段:
// ... 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
}
}

对于一个完整的(旧Junit4)工作测试示例,请查看:https://github.com/mercedes-benz/sechub/blob/3f176a8f4c00b7e8577c9e3bea847ecfc91974c3/sechub-administration/src/test/java/com/daimler/sechub/domain/administration/signup/SignupAdministrationRestControllerMockTest.java

相关内容

  • 没有找到相关文章

最新更新