我正在使用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验证运行时,多个集成测试失败并显示错误消息
javax.naming.NamingException:已存在另一个资源 name dataSource - 选择一个不同的名称
如果我使用JUnit @Ignore注释跳过此特定测试,一切都会恢复正常。
此行为似乎表明使用@MockBean更改了缓存行为,并且每个测试都尝试创建自己的数据源。我还应该提一下,我正在使用通过 XADataSourceAutoConfiguration 创建的 AtomikosDataSourceBean 。
如何解决此问题,以便我的集成测试仍然可以使用缓存上下文并同时使用@MockBean
?
答案 0 :(得分:1)
嗯,SomeService会以任何方式与您的数据源相关吗?
因为您的上下文被缓存而@MockBean执行以下操作:
用于向Spring ApplicationContext添加模拟...在上下文中定义的任何相同类型的现有单个bean将被模拟替换,
和
如果所请求类型的bean不止一个,则必须在字段级别指定限定符元数据:
@RunWith(SpringRunner.class)
public class ExampleTests {
@MockBean
@Qualifier("example")
private ExampleService service;
修改强>
因此,如果您的SomeService是DataSource的实现,请尝试添加限定符。如果SomeService中包含DataSource,并且您需要访问其中的某些方法,则可以尝试使用@Mock并指定需要通过自己的mock或autowire返回的任何对象。
@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();
}