Spring Boot 测试在 Maven 中失败,在 IntelliJ 中工作

Tob*_*obb 5 java maven spring-boot

我做了一个 Spring Boot 测试来测试 JMS 的消耗。

测试看起来像这样:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class UpdateThingByJmsIntegrationTest {

    @Test
    @Rollback(false)
    public void updateThingByJmsUpdatesDatabase() throws InterruptedException {
        final Thing thing = new ThingBuilder().withId(null).build();

        final TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        transactionTemplate.execute(transactionStatus -> {
            thingRepository.save(thing);
            return thing;
        });

        final String xml = String.format(
                "<thingDto><id>%s</id><name>something else</name><location>somewhere</location></thingDto>",
                thing.getId());

        jmsMessagingTemplate.convertAndSend(thingUpdateQueue, xml);

        Thread.sleep(1500L);

        final Thing updatedThing = thingRepository.getOne(thing.getId());

        assertNotNull(updatedThing);
        assertEquals("something else", updatedThing.getName());
        assertEquals("somewhere", updatedThing.getLocation());
    }
Run Code Online (Sandbox Code Playgroud)

Thing因此,我在数据库中保存一个,然后发送一条 JMS 消息来更新Thing. 由于 JMS 消耗发生在与测试本身不同的线程中,因此我等待,然后尝试验证是否Thing已更新。

Thing这在 IntelliJ 中工作得很好,但是当使用 Maven 运行它时,它会失败,因为使用 JMS 消息的线程无法在数据库中找到该消息。

我尝试ThingRepository在测试和使用 JMS 消息的代码中输出对象哈希码(标识符),但结果不同。对于 IntelliJ,它们是相同的。我怀疑这可能是问题的一部分,但我不确定如何避免它。

我还检查了 IntelliJ 与 Maven 中的日志输出,我发现 Maven 在测试运行之前就输出了这些行,而 IntelliJ 则没有。不知道是否相关。

2019-05-13 09:48:53.983  INFO 9271 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2019-05-13 09:48:53.995  INFO 9271 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2019-05-13 09:48:53.996  INFO 9271 --- [           main] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2019-05-13 09:48:54.000  INFO 9271 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Shutdown initiated...
2019-05-13 09:48:54.001  INFO 9271 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Shutdown completed.
Run Code Online (Sandbox Code Playgroud)

但是为什么我会在测试和被测类中得到不同的存储库对象?

更新:

事实证明,只有在与另一个测试同时运行相关测试时才会发生这种情况。在另一个测试中,我有:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class OtherIntegrationTest {
    @MockBean
    private ThingRepository thingRepository;
Run Code Online (Sandbox Code Playgroud)

看来这“渗透”到了我的其他测试,使上下文使用模拟,而我的测试使用真实的交易。有什么方法可以避免这种情况,或者我是否必须找到使用 @MockBean 的替代方法?

Kar*_*cki 2

这可能是由于缺乏适当的测试隔离造成的。如果updateThingByJmsUpdatesDatabase测试本身正常工作,并且在构建期间作为测试套件的一部分运行时失败,例如当使用mvn clean install.

您应该通过使用 Maven运行这个单一测试来验证这一点:

mvn test -Dtest=ClassName.updateThingByJmsUpdatesDatabase
Run Code Online (Sandbox Code Playgroud)