@MicronautTest - 限制实例化的内容
@MicronautTest - limit what is instantiated
每当我在我的项目中使用@MicronautTest
时,整个应用程序作为一个整体启动,因为某些事情需要在启动时由服务完成,所以它们也会被执行。
当我测试一个简单的控制器时,我不需要整个 Singleton shebang。
我的问题是在测试 Micronaut 时如何限制加载哪些控制器和单例?
我有一个演示问题的小示例
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>micronaut-test</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>2.5.1</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>2.5.1</micronaut.version>
<exec.mainClass>com.example.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths combine.children="append">
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=com.example</arg>
<arg>-Amicronaut.processing.module=micronaut-test</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.java
package com.example;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class, args);
}
}
一个简单的服务,只要实例化它就会抛出以指示问题
@Singleton
public class SingletonService {
@EventListener
public void init(ApplicationStartupEvent event) {
throw new RuntimeException("I was initialized");
}
}
一个简单的控制器
@Controller
public class TestController {
@Get
public Simple findAll() {
return new Simple("ATest");
}
public static class Simple {
private final String test;
public Simple(String test) {
this.test = test;
}
public String getTest() {
return test;
}
}
}
还有一个简单的测试
@MicronautTest
class TestControllerTest {
@Inject
@Client("/")
RxHttpClient rxHttpClient;
@Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
测试结果为
[INFO] Running com.example.controller.TestControllerTest
11:01:52.804 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [test]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 7.232 s <<< FAILURE! - in com.example.controller.TestControllerTest
[ERROR] com.example.controller.TestControllerTest Time elapsed: 7.229 s <<< ERROR!
java.lang.RuntimeException: I was initialized
如何防止测试启动该 SingletonService? Stubbing 是一种选择,但请记住,这是一个简单的演示,说明了更大项目的问题。没有其他直接的方法吗?
根据@MicronautTest 的 docs ,它不应该扫描类路径但它显然是?
以下是我已经尝试但未成功的其他一些配置:
添加禁用 eagerInit 的 ApplicationBuilder
@MicronautTest(application = TestControllerTest.TestApplication.class)
class TestControllerTest {
public static class TestApplication {
public static void main(String[] args) {
Micronaut.build(args)
.eagerInitAnnotated(null)
.eagerInitSingletons(false)
.mainClass(TestApplication.class);
}
}
@Inject
@Client("/")
RxHttpClient rxHttpClient;
@Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
传递上下文构建器
@MicronautTest(contextBuilder = TestControllerTest.TestContextBuilder.class)
class TestControllerTest {
public static class TestContextBuilder extends DefaultApplicationContextBuilder {
public TestContextBuilder() {
eagerInitSingletons(false);
eagerInitAnnotated(null);
eagerInitConfiguration(false);
}
}
@Inject
@Client("/")
RxHttpClient rxHttpClient;
@Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
它们都产生相同的响应。
希望有人知道如何使用 @MicronautTest 限制 bean 实例化的范围,否则我很可能会切换回 Spring boot
提前致谢
My question is how do I limit which controllers and singletons are
loaded when testing Micronaut?
至少有 @Requires
注解允许在当前环境中加载 bean 时进行灵活配置。
例如,在您的情况下应该是这样的:
import javax.inject.Singleton;
import io.micronaut.context.annotation.Requires;
@Singleton
@Requires(notEnv = {Environment.TEST})
public class SingletonService {
@EventListener
public void init(ApplicationStartupEvent event) {
throw new RuntimeException("I was initialized");
}
}
因此,服务没有抛出异常。
但是,我真的不知道您为什么需要排除该服务的目的。其他方法可能更方便。
例如,请参阅 micronaut 测试文档中的 Mocking Collaborators
部分:https://micronaut-projects.github.io/micronaut-test/latest/guide/
每当我在我的项目中使用@MicronautTest
时,整个应用程序作为一个整体启动,因为某些事情需要在启动时由服务完成,所以它们也会被执行。
当我测试一个简单的控制器时,我不需要整个 Singleton shebang。
我的问题是在测试 Micronaut 时如何限制加载哪些控制器和单例?
我有一个演示问题的小示例
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>micronaut-test</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>2.5.1</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>2.5.1</micronaut.version>
<exec.mainClass>com.example.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths combine.children="append">
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=com.example</arg>
<arg>-Amicronaut.processing.module=micronaut-test</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.java
package com.example;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class, args);
}
}
一个简单的服务,只要实例化它就会抛出以指示问题
@Singleton
public class SingletonService {
@EventListener
public void init(ApplicationStartupEvent event) {
throw new RuntimeException("I was initialized");
}
}
一个简单的控制器
@Controller
public class TestController {
@Get
public Simple findAll() {
return new Simple("ATest");
}
public static class Simple {
private final String test;
public Simple(String test) {
this.test = test;
}
public String getTest() {
return test;
}
}
}
还有一个简单的测试
@MicronautTest
class TestControllerTest {
@Inject
@Client("/")
RxHttpClient rxHttpClient;
@Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
测试结果为
[INFO] Running com.example.controller.TestControllerTest
11:01:52.804 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [test]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 7.232 s <<< FAILURE! - in com.example.controller.TestControllerTest
[ERROR] com.example.controller.TestControllerTest Time elapsed: 7.229 s <<< ERROR!
java.lang.RuntimeException: I was initialized
如何防止测试启动该 SingletonService? Stubbing 是一种选择,但请记住,这是一个简单的演示,说明了更大项目的问题。没有其他直接的方法吗? 根据@MicronautTest 的 docs ,它不应该扫描类路径但它显然是?
以下是我已经尝试但未成功的其他一些配置:
添加禁用 eagerInit 的 ApplicationBuilder
@MicronautTest(application = TestControllerTest.TestApplication.class)
class TestControllerTest {
public static class TestApplication {
public static void main(String[] args) {
Micronaut.build(args)
.eagerInitAnnotated(null)
.eagerInitSingletons(false)
.mainClass(TestApplication.class);
}
}
@Inject
@Client("/")
RxHttpClient rxHttpClient;
@Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
传递上下文构建器
@MicronautTest(contextBuilder = TestControllerTest.TestContextBuilder.class)
class TestControllerTest {
public static class TestContextBuilder extends DefaultApplicationContextBuilder {
public TestContextBuilder() {
eagerInitSingletons(false);
eagerInitAnnotated(null);
eagerInitConfiguration(false);
}
}
@Inject
@Client("/")
RxHttpClient rxHttpClient;
@Test
void controller() {
HttpResponse<ByteBuffer> byteBufferHttpResponse = rxHttpClient.exchange("/").blockingFirst();
assert byteBufferHttpResponse.getStatus().getCode() == 200;
}
}
它们都产生相同的响应。
希望有人知道如何使用 @MicronautTest 限制 bean 实例化的范围,否则我很可能会切换回 Spring boot
提前致谢
My question is how do I limit which controllers and singletons are loaded when testing Micronaut?
至少有 @Requires
注解允许在当前环境中加载 bean 时进行灵活配置。
例如,在您的情况下应该是这样的:
import javax.inject.Singleton;
import io.micronaut.context.annotation.Requires;
@Singleton
@Requires(notEnv = {Environment.TEST})
public class SingletonService {
@EventListener
public void init(ApplicationStartupEvent event) {
throw new RuntimeException("I was initialized");
}
}
因此,服务没有抛出异常。
但是,我真的不知道您为什么需要排除该服务的目的。其他方法可能更方便。
例如,请参阅 micronaut 测试文档中的 Mocking Collaborators
部分:https://micronaut-projects.github.io/micronaut-test/latest/guide/