spring 集成测试无法加载上下文“另一个资源已经存在,名称为 dataSource”
Posted
技术标签:
【中文标题】spring 集成测试无法加载上下文“另一个资源已经存在,名称为 dataSource”【英文标题】:spring integration test fail to load context "Another resource already exists with name dataSource" 【发布时间】:2017-06-14 05:51:09 【问题描述】:我正在使用 spring-boot 1.4.3 中引入的测试注释进行集成测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceIT
根据documentation,测试上下文被缓存并重用以加速集成测试。这种行为是我想要的,因为初始化应用程序上下文需要大量时间。我的故障安全插件配置了
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
允许集成测试在同一进程中运行,以利用应用程序上下文缓存。
最近,我编写了一个集成测试,使用 @MockBean 注解来模拟某些 bean 的行为。
@RunWith(SpringRunner.class)
@SpringBootTest
public class AnotherServiceIT
@MockBean
SomeService service1
虽然测试本身运行良好,但通过 maven verify 运行时,多个集成测试失败并显示错误消息
javax.naming.NamingException:另一个资源已经存在 命名 dataSource - 选择不同的名称
如果我使用 JUnit @Ignore 注解跳过这个特定的测试,一切都会恢复正常。
这种行为似乎表明使用@MockBean 改变了缓存行为,并且每个测试都尝试创建自己的数据源。我还应该提到我正在使用通过 XADataSourceAutoConfiguration 创建的 AtomikosDataSourceBean。
我该如何克服这个问题,以便我的集成测试仍然可以使用缓存的上下文并同时使用@MockBean
?
【问题讨论】:
spring-boot 会不会是这个问题? github.com/spring-projects/spring-boot/issues/7174 感谢您指出问题。我使用的是 spring-boot 1.4.3,这个问题应该已经解决了。我会做一些调试来看看是不是这样。 【参考方案1】:嗯,SomeService 是否与您的数据源有任何关系?
因为您的上下文被缓存并且@MockBean 执行以下操作:
用于将 mocks 添加到 Spring ApplicationContext ... 任何现有的在上下文中定义的相同类型的单个 bean 都将被 mock 替换,
和
如果请求类型的 bean 不止一个,则必须在字段级别指定限定符元数据:
@RunWith(SpringRunner.class)
public class ExampleTests
@MockBean
@Qualifier("example")
private ExampleService service;
编辑:
因此,如果您的 SomeService 是 DataSource 的实现,请尝试添加限定符。如果 SomeService 中有一个 DataSource,并且您需要访问其中的某些方法,您可以尝试使用 @Mock 并指定需要通过自己的模拟或自动装配返回的任何对象。
@Mock
SomeService someService;
@Mock
SomeDependency mockDependency;
@Autowired
OtherDependency realDependency;
@Before
public void setUp()
MockitoAnnotations.initMocks(this);
doReturn(mockDependency).when(someService).getSomeDependency();
doReturn(realDependency).when(someService).getOtherDependency();
【讨论】:
以上是关于spring 集成测试无法加载上下文“另一个资源已经存在,名称为 dataSource”的主要内容,如果未能解决你的问题,请参考以下文章
JUnit 4 & Spring Boot - 在测试前有选择地重新加载上下文/重新加载 Spring Security 配置