运行 单元测试时多次创建 RmiRegistry
RmiRegistry created multiple times when running unit tests
我的 Spring 引导应用程序有一个 bean:
@Configuration
public class JmxRmiConfig {
@Value("${jmx.rmi.host:localhost}")
private String rmiHost;
@Value("${jmx.rmi.port:1099}")
private Integer rmiPort;
@Bean
public RmiRegistryFactoryBean rmiRegistry() {
final RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
rmiRegistryFactoryBean.setPort(rmiPort);
rmiRegistryFactoryBean.setAlwaysCreate(true);
return rmiRegistryFactoryBean;
}
@Bean
@DependsOn("rmiRegistry")
public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setObjectName("connector:name=rmi");
connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", rmiHost, rmiPort, rmiHost, rmiPort));
return connectorServerFactoryBean;
}
}
我有两个单元测试都这样注释:
@AutoConfigureMockMvc
@SpringBootTest
@Unroll
class ... extends Specification { ... }
(展开和规范均来自spock.lang)
当我 运行 它们一起使用 maven/surefire 时,第二个测试 class 失败,出现此错误:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'rmiRegistry' defined in class path resource
[uk/ac/prospects/hedd/api/config/JmxRmiConfig.class]: Invocation of
init method failed; nested exception is
java.rmi.server.ExportException: internal error: ObjID already in use
它似乎正在为第二个 class 重新创建 RmiRegistry,而没有破坏第一个。
因为我有其他没有@AutoConfigureMockMvc 的测试 运行 在一起很好,我的假设是 @AutoConfigureMockMvc 触发了问题。
如何让两个测试一起 运行?
surefire 插件的以下附加配置为我们解决了这个问题。
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
不理解 100% 的问题,但我们添加了上述内容,因为测试套件在 Spring 个 beans 之间混淆,这些 beans 在一个测试中被模拟,但在另一个测试中配置正确。这也解决了 RMI bean 问题。我认为这为每个测试提供了一个干净的 Spring 上下文。
我没有对此进行测试,但认为 Spring 测试框架注释 @DirtiesContext 可能有一个解决方案:https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-testing-annotation-dirtiescontext
我的 Spring 引导应用程序有一个 bean:
@Configuration
public class JmxRmiConfig {
@Value("${jmx.rmi.host:localhost}")
private String rmiHost;
@Value("${jmx.rmi.port:1099}")
private Integer rmiPort;
@Bean
public RmiRegistryFactoryBean rmiRegistry() {
final RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
rmiRegistryFactoryBean.setPort(rmiPort);
rmiRegistryFactoryBean.setAlwaysCreate(true);
return rmiRegistryFactoryBean;
}
@Bean
@DependsOn("rmiRegistry")
public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setObjectName("connector:name=rmi");
connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", rmiHost, rmiPort, rmiHost, rmiPort));
return connectorServerFactoryBean;
}
}
我有两个单元测试都这样注释:
@AutoConfigureMockMvc
@SpringBootTest
@Unroll
class ... extends Specification { ... }
(展开和规范均来自spock.lang)
当我 运行 它们一起使用 maven/surefire 时,第二个测试 class 失败,出现此错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rmiRegistry' defined in class path resource [uk/ac/prospects/hedd/api/config/JmxRmiConfig.class]: Invocation of init method failed; nested exception is java.rmi.server.ExportException: internal error: ObjID already in use
它似乎正在为第二个 class 重新创建 RmiRegistry,而没有破坏第一个。
因为我有其他没有@AutoConfigureMockMvc 的测试 运行 在一起很好,我的假设是 @AutoConfigureMockMvc 触发了问题。
如何让两个测试一起 运行?
surefire 插件的以下附加配置为我们解决了这个问题。
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
不理解 100% 的问题,但我们添加了上述内容,因为测试套件在 Spring 个 beans 之间混淆,这些 beans 在一个测试中被模拟,但在另一个测试中配置正确。这也解决了 RMI bean 问题。我认为这为每个测试提供了一个干净的 Spring 上下文。
我没有对此进行测试,但认为 Spring 测试框架注释 @DirtiesContext 可能有一个解决方案:https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-testing-annotation-dirtiescontext