Spring引导@SpyBean导致测试套件出错,可能是由于上下文未被重置的问题

时间:2017-03-23 08:54:38

标签: spring spring-boot dependency-injection spring-test spring-boot-test

我遇到弹簧集成测试的问题。

行为:

  • 当我单独进行下面的测试时,它是成功的。

  • 但是,当所有测试都运行时,其中许多测试都包含错误。

  • 当我忽略下面的测试并运行所有测试时,所有测试都成功。

我还没有包含错误堆栈跟踪,因为它与我们的业务逻辑高度相关,我怀疑错误与我使用spring boot test @SpyBean有关。

以下是测试:

@RunWith(SpringRunner.class)
@ActiveProfiles(profiles = "test")
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

...

@Autowired
private TestRestTemplate restTemplate;

@Autowired
private DataKeyStore dataKeyStore;

@SpyBean
private TokenTools tokenTools;

...

@Test
public void myTest() throws Exception {

   doReturn("someGeneratedToken")
        .doReturn("someGeneratedToken")
        .doCallRealMethod()
        .when(tokenTools)
        .createToken(any(TokenProfile.class), anyString(), anyString());
  ...

请注意,DataKeyStoreTokenTools的依赖关系。

正如我上面所说,我怀疑测试正在相互踩踏,而我的@SpyBean在某些方面泄露了其他测试类......

我的问题是如何确保此测试不会踩到其他测试?我试过@DirtiesContext注释无济于事......

令我困惑的是,@SpyBean已经重置(根据文档/ javadoc)。

有人可以帮忙吗?

编辑:使用我的IDE调试测试表明TokenTools仅针对所有测试实例化两次:一次是在测试初始化​​,另一次是创建{{1对于上面的测试。在上面的测试之后运行的其余测试使用第二个实例,即@SpyBean实例......

2 个答案:

答案 0 :(得分:1)

我最近遇到了同样的问题。确保为您的设置正确的classMode @DirtiesContext注释。

默认情况下,@DirtiesContext将在完成完整的测试课程后重置@SpyBean。您可能想在每种测试方法之前或之后将其重置。

因此,将@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)添加到测试类中。

答案 1 :(得分:0)

我可以确认@DirtiesContext对我们来说也不起作用。在旧的上下文关闭后(通过@DirtiesContext注释),我们在初始化DB(使用Liquibase)时遇到了新问题。

我们最终以不同的方式命名Spring测试上下文用于伪造某些bens的测试:

E.g:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = SpringBootApp.class, name = "mainContext")
public class TestThatDoesntFakeBeans(){
}

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = SpringBootApp.class, name = "contextWithFakeBean")
public class TestThatFakeBeans(){
    @SpyBean
    //...
}

这样就为每个名称创建了单独的Spring上下文。具有相同名称的上下文将通过测试重用。但是,当然您需要确保具有相同上下文名称的测试不会相互影响。