我有一个Spring启动应用程序,它启动并执行一个类,它监听Application Ready事件以调用外部服务来获取一些数据,然后使用该数据将一些规则推送到类路径以便执行.对于本地测试,我们在应用程序启动期间模拟了应用程序中的外部服务.
该问题是在测试与运行它的应用程序春天开机测试注释和嵌入式码头集装箱无论是在:
在RANDOM PORT的情况下,在应用程序启动时,它从定义端口的属性文件中获取模拟服务的url,并且不知道嵌入式容器正在运行的位置,因为它是随机拾取的,因此无法给出响应.
在DEFINED PORT的情况下,对于第一个测试用例文件,它成功运行,但是当下一个文件被拾取时,它说该端口已经在使用中失败.
测试用例在逻辑上分区为多个文件,并且需要在容器开始加载规则之前调用外部服务.
如果使用已定义的端口,则如何在测试文件之间共享嵌入式容器,或者在测试用例执行期间启动时重构我的应用程序代码以获取随机端口.
任何帮助,将不胜感激.
应用程序启动代码:
@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
private SomeService someService;
@Override
public void onApplicationEvent(ApplicationReadyEvent arg0) {
try {
someService.callExternalServiceAndLoadData();
}
catch (Execption e) {}
}
}
Run Code Online (Sandbox Code Playgroud)
测试代码注释:Test1
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test1 {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void tc1() throws IOException {.....}
Run Code Online (Sandbox Code Playgroud)
测试代码注释:Test2
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment …Run Code Online (Sandbox Code Playgroud) 确信没有人问过这个问题,但是通过阅读 Spring 文档和测试实用程序,我发现了这个注释,并认为我会开始使用它。通读小字,我读到:
常规的@Component bean 不会加载到 ApplicationContext 中。
这听起来不错,我什至喜欢使用 H2 的想法,除了我发现我想要使用的实体具有目录和模式修饰符,而默认的 H2 我不知道如何支持它。我为测试分支创建了一个 H2 数据源并使用它并覆盖替换。我结束了
@RunWith(SpringRunner.class)
@ContextConfiguration(classes=ABCH2Congfiguration.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
public class StatusRepositoryTest {
}
Run Code Online (Sandbox Code Playgroud)
但是我的测试失败了原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有符合类型的bean。这导致:创建名为“customerServiceImpl”的 bean 时出错:依赖项不满足。
但是 customerServiceImpl 是这个 bean:
@Component
public class CustomerServiceImpl implements CustomerService {
}
Run Code Online (Sandbox Code Playgroud)
那就是@Component。DataJpaTest 的细则说它不加载@Components。为什么它会这样做,从而导致测试失败?
正如凯尔和尤金在下面问的那样,剩下的就是:
package com.xxx.abc.triage;
@Component
public interface CustomerService {
}
Configuration
@ComponentScan("com.xxx.abc")
@EnableJpaRepositories("com.xxx.abc")
//@Profile("h2")
public class ABMH2Congfiguration {
@Primary
@Bean(name = "h2source")
public DataSource dataSource() {
EmbeddedDatabase build = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).setName("ABC").addScript("init.sql").build();
return build;
}
@Bean
public JpaVendorAdapter …Run Code Online (Sandbox Code Playgroud) 我们正在尝试使用 spring boot 1.4.0 版对我们的 spring boot 应用程序中的拦截器进行集成测试,但不确定如何;这是我们的应用程序设置
@Configuration
@EnableAutoConfiguration()
@ComponentScan
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilderconfigure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
Run Code Online (Sandbox Code Playgroud)
然后我们通过扩展 WebMvcConfigurerAdapter 来定制 webmvc
@Configuration
public class CustomServletContext extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(testInterceptor).addPathPatterns("/testapi/**");
}
}
Run Code Online (Sandbox Code Playgroud)
所以我们想测试拦截器,但我们不想真正启动应用程序,因为有很多依赖bean需要读取外部定义的属性文件来构造
我们尝试了以下方法
@SpringBootTest(classes = CustomServletContext.class)
@RunWith(SpringRunner.class)
public class CustomServletContextTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void interceptor_request_all() throws Exception {
RequestMappingHandlerMapping mapping = (RequestMappingHandlerMapping) applicationContext
.getBean("requestMappingHandlerMapping");
assertNotNull(mapping);
MockHttpServletRequest request = new MockHttpServletRequest("GET",
"/test");
HandlerExecutionChain chain = …Run Code Online (Sandbox Code Playgroud) 运行 spring boot 测试的推荐方法是什么,其中仅在上下文中配置了一个被测主题。
如果我用
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.profiles.active=test")
@ContextConfiguration(classes = MyTestBean.class)
Run Code Online (Sandbox Code Playgroud)
然后它似乎工作 - 测试通过,上下文快速启动并且似乎只包含我想要的 bean。但是,这似乎是对@ContextConfiguration(classes = MyTestBean.class)注释的错误使用。如果我理解正确,我引用的类应该是一个Configuration类,而不是一个常规的 spring 服务 bean 或组件。
那正确吗?或者这确实是实现这一目标的有效方法?我知道有更复杂的例子一样org.springframework.boot.test.autoconfigure.json.JsonTest,其使用@TypeExcludeFilters(JsonExcludeFilter.class)控制方面-但这似乎矫枉过正我的使用情况。我只想要我的一个 bean 的上下文。
我知道我可以在没有 spring 上下文测试的情况下将我正在测试的一个 bean 构建为 POJO,并删除上面的三个注释。但在我的精确用例中,我实际上依赖于通过设置中的设置应用于上下文的一些配置application-test.properties文件 - 这就是为什么我使用配置文件集将其作为 Spring Boot 测试的原因。从我的角度来看,这不是孤立于 spring 上下文配置的单个类的简单单元测试 - 该测试依赖于正在应用的某些配置(当前由 spring boot 应用程序属性提供)。我确实可以通过在 spring 上下文之外创建一个新实例来将组件作为 POJO 进行测试,我使用构造函数注入使提供必要的依赖项变得简单,但测试确实依赖于诸如日志级别之类的东西(测试实际上使正在生成的某些日志上的断言),这需要正确设置日志级别(目前正在通过logging.level.com.example=DEBUG设置 spring 上下文的属性文件完成)。
我刚刚升级了我的项目以使用Spring Boot 2.1.0(之前是2.0.x)并且我有编译警告:
[WARNING] Cannot find annotation method 'value()' in type 'org.junit.jupiter.api.extension.ExtendWith': class file for org.junit.jupiter.api.extension.ExtendWith not found
Run Code Online (Sandbox Code Playgroud)
我可以添加依赖org.junit.jupiter/junit-jupiter-api来解决警告,但我觉得这是'黑客'.
我不希望看到这个警告(特别是我的项目处理错误等警告),我不想用不必要的依赖项来污染我的项目.
我正在使用Maven,但我可以看到有人遇到与Gradle相同的问题 https://www.reddit.com/r/java/comments/9sogxf/spring_boot_210_released_now_with_java_11_support/
在大多数集成测试中,我使用 spring-boot-test(2.1.9.RELEASE) 和 spring-cloud-contract-wiremock(2.0.2.RELEASE)。测试基于 @AutoConfigureWireMock(port = 0) 启动 WireMock 服务器,因此我没有使用任何 WireMockRule 或其他配置设置。
有时验证失败并出现一个非常奇怪的错误:
com.github.tomakehurst.wiremock.client.VerificationException:` com.github.tomakehurst.wiremock.client.VerificationException:com.github.tomakehurst.wiremock.client.VerificationException:没有完全匹配的请求。最相似的请求是:预期:< POST /api/id/delete
但是:< POST /api/id/delete
正如您在上面看到的,预期端点与实际调用完全相同。
你有什么想法 ?或者你以前见过吗?这里有一个未解决的问题: https: //github.com/tomakehurst/wiremock/issues/706,但回复不是很有帮助。
我想为我的 RestAPI 端点编写集成测试,但我正在努力解决 @EnableJpaAuditing。我希望 Spring 审核我的一些实体,因此我创建了以下配置类:
@Configuration
@EnableJpaAuditing
public class PersistenceAuditConfiguration {
}
Run Code Online (Sandbox Code Playgroud)
我将其导入到我的主应用程序配置中:
@ServletComponentScan
@SpringBootApplication
@Import(PersistenceAuditConfiguration.class)
public class TMTWebApplication {
public static void main(String[] args) {
SpringApplication.run(TMTWebApplication.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
另外,我有一个针对我想要审核的所有实体的抽象基类:
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"}, allowGetters = true)
public abstract class AuditableEntity extends EpicPojo implements Serializable {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at", nullable = false, updatable = false)
@CreatedDate
private Date createdAt;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated_at", nullable = false)
@LastModifiedDate
private Date updatedAt;
//...and so on
}
Run Code Online (Sandbox Code Playgroud)
在我的 …
我正在尝试利用 H2 进行测试并在 中有以下配置src/test/resources/application.yaml:
spring:
r2dbc:
url: r2dbc:h2:file://testdb
Run Code Online (Sandbox Code Playgroud)
我有一个带有注释的空测试,@SpringBootTest但是当我运行它时,出现以下错误:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.r2dbc.pool.ConnectionPool]: Factory method 'connectionFactory' threw exception; nested exception is java.lang.IllegalStateException: Unable to create a ConnectionFactory for 'ConnectionFactoryOptions{options={driver=h2, protocol=file, host=testdb}}'. Available drivers: [ pool, postgresql, h2 ]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
... 131 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to create a ConnectionFactory for 'ConnectionFactoryOptions{options={driver=h2, protocol=file, host=testdb}}'. Available drivers: [ pool, postgresql, h2 ]
at io.r2dbc.spi.ConnectionFactories.get(ConnectionFactories.java:145)
at org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBuilder.build(ConnectionFactoryBuilder.java:125)
at org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations.createConnectionFactory(ConnectionFactoryConfigurations.java:56)
at …Run Code Online (Sandbox Code Playgroud) 我的Spring Boot应用程序启动如下:
new SpringApplicationBuilder()
.sources(ParentCtxConfig.class)
.child(ChildFirstCtxConfig.class)
.sibling(ChildSecondCtxConfig.class)
.run(args);
Run Code Online (Sandbox Code Playgroud)
配置类使用注释@SpringBootApplication.因此,我有一个根上下文和两个子Web上下文.
我想编写集成测试,我希望在那里有相同的上下文层次结构.我希望至少ChildFirstCtxConfig.class用他的父上下文(ParentCtxConfig.class)测试第一个子上下文(配置).我怎样才能做到这一点?
目前我ApplicationContext在我的测试中自动装配,所以我可以检查它.我在测试中有这个类注释:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
Run Code Online (Sandbox Code Playgroud)
但这将产生单个上下文,我想要父子层次结构.我假设我应该用@ContextHierarchy注释来注释我的测试.
将我的测试注释更改为这似乎与前面的示例完全相同:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class })
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
Run Code Online (Sandbox Code Playgroud)
但是,如果我想介绍@ContextHierarchy并有这样的事情:
@RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "root", classes = ParentCtxConfig.class),
@ContextConfiguration(name = "child", classes = ChildFirstCtxConfig.class)
})
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
Run Code Online (Sandbox Code Playgroud)
由于在父上下文中定义的bean无法在子上下文中找到/自动装配,因此未启动上下文.设置loader = SpringBootContextLoader.class没有帮助.
示例代码:GitHub
我正在使用spring boot 1.5.8并想测试我的客户端:
@Component
public class RestClientBean implements RestClient {
private Map<String, RestTemplate> restTemplates = new HashMap<>();
@Autowired
public RestClientBean(RestTemplateBuilder builder, SomeConfig conf) {
restTemplates.put("first", builder.rootUri("first").build();
restTemplates.put("second", builder.rootUri("second").build();
}
}
Run Code Online (Sandbox Code Playgroud)
通过以下测试:
@RunWith(SpringRunner.class)
@RestClientTest(RestClient.class)
public class RestClientTest {
@Autowired
private RestClient client;
@Autowired
private MockRestServiceServer server;
@TestConfiguration
static class SomeConfigFooBarBuzz {
@Bean
public SomeConfig provideConfig() {
return new SomeConfig(); // btw. not sure why this works,
// but this is the only way
// I got rid of the "unable to …Run Code Online (Sandbox Code Playgroud) spring-boot-test ×10
spring-boot ×8
java ×7
spring ×3
spring-test ×2
auditing ×1
h2 ×1
r2dbc ×1
resttemplate ×1
spring-mvc ×1
wiremock ×1