QuarkusIntegrationTest不允许连续运行两个测试:应用程序在第二次测试中通过Camel SimpleMainShutdownStrategy关闭

ocebsuys  于 2023-01-09  发布在  Apache
关注(0)|答案(1)|浏览(90)

我有一个奇怪的错误:我只能在我的mvn verify步骤中运行一个Quarkus集成测试。当我有两个集成测试时,第二个运行但立即停止应用程序,所以什么都没有发生,构建永远挂起。
两次测试的日志不同,第一次测试的日志为:

2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main) Routes startup (total:8 started:8)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started route1 (activemq://queue:myqueue)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started route2 (activemq://queue:myqueue.online)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started main (direct://main)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started individual-endpoint (direct://individual-endpoint)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started send-and-retry (direct://send-and-retry)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started mapping-response (direct://mapping-response)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started reply-queue (direct://reply-queue)
2023-01-04 15:43:04,560 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started route3 (direct://receive.ack.response)
2023-01-04 15:43:04,561 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main) Apache Camel 3.14.1 (camel-1) started in 593ms (build:0ms init:206ms start:387ms)
2023-01-04 15:43:04,562 DEBUG [org.apa.cam.imp.DefaultCamelContext] (main) start() took 594 millis
2023-01-04 15:43:04,567 DEBUG [org.apa.cam.mai.SimpleMainShutdownStrategy] (camel-main) Await shutdown to complete
2023-01-04 15:43:04,583 INFO  [com.example.MyLogger] (main) Application is up
2023-01-04 15:43:04,583 INFO  [com.example.MyLogger] (main) Application is up
2023-01-04 15:43:04,767 INFO  [com.example.ShutdownController] (main) Setting pre shutdown sleep time to 10 seconds.
2023-01-04 15:43:04,767 INFO  [io.quarkus] (main) my-app 0.0.1-SNAPSHOT on JVM (powered by Quarkus 2.7.5.Final) started in 3.124s. Listening on: http://0.0.0.0:8081
2023-01-04 15:43:04,768 INFO  [io.quarkus] (main) Profile integration activated.
    ...(application runs normally; sends a message to in memory AMQ broker and Camel starts consuming from the queue)

第二次测试运行时使用以下日志:

2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main) Routes startup (total:8 started:8)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started route1 (activemq://queue:myqueue)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started route2 (activemq://queue:myqueue.online)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started main (direct://main)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started individual-endpoint (direct://individual-endpoint)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started send-and-retry (direct://send-and-retry)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started mapping-response (direct://mapping-response)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started reply-queue (direct://reply-queue)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main)     Started route3 (direct://receive.ack.response)
2023-01-04 15:43:59,606 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main) Apache Camel 3.14.1 (camel-1) started in 452ms (build:0ms init:202ms start:250ms)
2023-01-04 15:43:59,607 DEBUG [org.apa.cam.imp.DefaultCamelContext] (main) start() took 453 millis
2023-01-04 15:43:59,631 INFO  [com.example.MyLogger] (main) Application is up
2023-01-04 15:43:59,631 INFO  [com.example.MyLogger] (main) Application is up
2023-01-04 15:43:59,617 DEBUG [org.apa.cam.mai.SimpleMainShutdownStrategy] (camel-main) Await shutdown to complete
2023-01-04 15:43:59,756 INFO  [com.example.MyLogger] (main) Application is down
2023-01-04 15:43:59,756 INFO  [com.example.MyLogger] (main) Application is down
2023-01-04 15:43:59,757 DEBUG [org.apa.cam.mai.SimpleMainShutdownStrategy] (main) Shutdown called
2023-01-04 15:43:59,757 DEBUG [org.apa.cam.mai.MainLifecycleStrategy] (main) CamelContext: camel-1 is stopping, triggering shutdown of the JVM.

ShutdownController侦听Quarkus关闭事件。

public class ShutdownController implements ShutdownListener {
    static final Logger LOGGER = LoggerFactory.getLogger(ShutdownController.class);
    private final long preShutdownSleep;

    public ShutdownController() {
        this.preShutdownSleep = (Long)ConfigProvider.getConfig().getOptionalValue("com.example.shutdown-controller.pre-shutdown-sleep", Long.class).orElse(ProfileManager.getLaunchMode() == LaunchMode.TEST ? 0L : 10L);
        LOGGER.info("Setting pre shutdown sleep time to {} seconds.", this.preShutdownSleep);
    }

    public ShutdownController(final int preShutdownSleep) {
        this.preShutdownSleep = (long)preShutdownSleep;
    }

    public void preShutdown(final ShutdownNotification notification) {
        LOGGER.info("Pre shutdown received. Waiting fully functionally for {} seconds.", this.preShutdownSleep);
        this.sleep();
        LOGGER.info("Continuing shutdown");
        notification.done();
    }

    private void sleep() {
        try {
            TimeUnit.SECONDS.sleep(this.preShutdownSleep);
        } catch (InterruptedException var2) {
            Thread.currentThread().interrupt();
        }

    }
}

请注意,Camel SimpleMainShutdownStrategy被调用,但在第二个测试中,它没有等待10 s。为什么?
我在SimpleMainShutdownStrategy类中看到这部分:

@Override
    public boolean isRunAllowed() {
        return !completed.get();
    }

    @Override
    public void addShutdownListener(ShutdownEventListener listener) {
        listeners.add(listener);
    }

    @Override
    public boolean shutdown() {
        if (completed.compareAndSet(false, true)) {
            LOG.debug("Shutdown called");
            latch.countDown();
            for (ShutdownEventListener l : listeners) {
                try {
                    LOG.trace("ShutdownEventListener: {}", l);
                    l.onShutdown();
                } catch (Throwable e) {
                    // ignore as we must continue
                    LOG.debug("Error during ShutdownEventListener: {}. This exception is ignored.", l, e);
                }
            }
            return true;
        }

        return false;
    }

    @Override
    public void await() throws InterruptedException {
        LOG.debug("Await shutdown to complete");
        latch.await();
    }

所以可能是第一种情况ShutdownController没有示例,所以调用构造函数,等待10 s;但是在第二个测试中,创建了示例,所以它不调用构造函数。但是为什么在集成测试运行之前调用shutdown呢?
在这两种情况下,Quarkus应用程序在Camel之前启动。
两项测试的结构相似:

@QuarkusIntegrationTest
@QuarkusTestResource(value = WiremockResource.class, restrictToAnnotatedClass = true)
@QuarkusTestResource(value = InMemoryAMQResource.class, restrictToAnnotatedClass = true)
@TestProfile(MyIntegrationTestProfile.class)
class MyOutboundMessageFormatIT extends MyIntegrationTestSupport { // the base class have a lot of fields like connetion, session, etc., which are used in @BeforeAll and @BeforeEach, etc. 
    private static final Logger LOG = Logger.getLogger(MyOutboundMessageFormatIT.class);

    @InjectInMemoryAMQ
    protected BrokerService brokerService;

    @InjectWiremock
    protected WireMockServer wireMockServer;

    @Override
    WireMockServer getWiremock() {
        return wireMockServer;
    }

    @Override
    BrokerService getBroker() {
        return brokerService;
    }

    @BeforeAll
    protected static void start() throws Exception {
        LOG.debug("Connecting to AMQ");
        connectToAMQ();
    }

    @AfterAll
    protected static void stop() throws Exception {
        LOG.debug("Stopping AMQ");
        session.close();
        connection.stop();
        connection.close();
    }

    @BeforeEach
    protected void stub() {
        // global stubs
        stubAllFieldsOK();
        stubOauthOK();
    }

    @AfterEach
    protected void clearWiremockRequestsJournal() throws JMSException {
        // clear reply queue for next test
        consumeOnlineReply();
        assertEmptyNonOnlineReply();
        waitTillTokenExpires();
        wireMockServer.resetRequests();
    }
    ...
ttisahbt

ttisahbt1#

最后,在日志的末尾,我看到了原因:

2023-01-05 14:13:52,530 INFO  [org.apa.cam.imp.eng.AbstractCamelContext] (main) Apache Camel 3.14.1 (camel-1) shutdown in 942ms (uptime:1s341ms)
2023-01-05 14:13:52,549 ERROR [io.qua.run.Application] (main) Port 8081 seems to be in use by another process. Quarkus may already be running or the port is used by another application.
2023-01-05 14:13:52,549 WARN  [io.qua.run.Application] (main) Use 'netstat -anop | grep 8081' to identify the process occupying the port.
2023-01-05 14:13:52,549 WARN  [io.qua.run.Application] (main) You can try to kill it with 'kill -9 <pid>'.

因此,实际上不能运行2个集成测试; Quarkus应用程序似乎只能启动一次并将占用端口。
最后,我解决了这个问题,方法是允许内存代理URL中的ActiveMQ中存在重复消息,并将所有情况放在一个测试中。
最初的问题是我在测试之间重用JSON消息体,而ActiveMQ不知何故忽略了消息,因此没有消息进入队列,所以第二个测试没有运行;此外,改变Wiremock资源类的stubbing似乎是不可能的(一开始我让Wiremock返回200,但在最后一个测试中我想模拟404的情况),这就是为什么我想分开测试。
现在,我用一个id来标记我想要修改的存根,在测试中我调用wiremockServer.editStub()来修改存根,同时我停止了与@TestMethodOrder(value = MethodOrderer.MethodName.class)并行运行的测试,然后事情就开始工作了,所以现在不需要分成两个测试类。

相关问题