为什么存根 sftp Camel 端点不遵守此测试中的 "include" 选项?

Why isn't a stubbed sftp Camel endpoint respecting the "include" option in this test?

我正在尝试存根一个 sftp 消费者端点以用于测试目的 - 我还不想尝试启动一个容器。这是我到目前为止所得到的:

import org.apache.camel.*;
import org.apache.camel.builder.AdviceWith;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.apache.camel.test.spring.junit5.MockEndpointsAndSkip;
import org.apache.camel.test.spring.junit5.UseAdviceWith;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;

import static org.junit.jupiter.api.Assertions.assertTrue;


import java.io.File;
import static com.routes.zipping.Resources.*;

/**
 * Tests a from() route, the scheme of which is not "direct", but is "sftp".
 */

@CamelSpringBootTest
@SpringBootTest(properties = "camel.springboot.java-routes-include-pattern=**/GetWretchedBillImagesRoute*")
@MockEndpointsAndSkip("direct:split")
@UseAdviceWith
public class ITGetWretchedBIllImagesRoute {

    @Produce
    ProducerTemplate producerTemplate;

    @Autowired
    CamelContext camelContext;

    @EndpointInject("mock:direct:split")
    MockEndpoint mockConvert;

    private String stubUrl;

    @Test
    @DisplayName("ZIPs are count")
    @DirtiesContext
    @Disabled("This gives back inconsistent results or seems to ignore the 'include' file option, so zip of any name or even a pdf is received at mocked endpoint.")
    void testGetFile_ZipMessageCountsButNotPdf() throws Exception {
        File zip = new File(TEST_PATH + ZIP + IN + "zipWith3Files.zip");
        assertTrue(zip.exists(), "The required test resource file is unavailable");

        File pdf = new File(TEST_PATH + PDF + IN + "myPdf.pdf");
        assertTrue(pdf.exists(), "The required test resource file is unavailable");

        AdviceWith.adviceWith(camelContext, "Wretched Bill Image ZIP Poller", routeBuilder -> {
            RouteDefinition rd = routeBuilder.getOriginalRoute();
            rd.setAutoStartup("true");
            var originalUrl = rd.getEndpointUrl();
            System.out.println("Advicing " + originalUrl);
            stubUrl = "stub:" + originalUrl;
            routeBuilder.replaceFromWith(stubUrl);
        });

        camelContext.start();

        mockConvert.expectedMessageCount(0);

        producerTemplate.sendBody(stubUrl, zip);
        producerTemplate.sendBody(stubUrl, zip);
        producerTemplate.sendBody(stubUrl, pdf);
        producerTemplate.sendBody(stubUrl, pdf);

        mockConvert.assertIsSatisfied();
    }
}

这里是原路线:

import com.routes.client.props.WretchedRouteProps;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class GetWretchedBillImagesRoute extends RouteBuilder {
    public static String ROUTE_ID = "Wretched Bill Image ZIP Poller";

    private final WretchedRouteProps arp;

    @Autowired
    public GetWretchedBillImagesRoute(WretchedRouteProps wretchedRouteProps) {
        this.arp = wretchedRouteProps;
    }

    //@formatter:off
    @Override
    public void configure() throws Exception {
        from(getSftpStartEndpoint())
                .log("Polled for zipped image files for Wretched")
                .id("Wretched Bill Image ZIP Poller")
                .routeId("Wretched Bill Image ZIP Poller")
                .setHeader("unzipTo", constant(arp.getFileDestination()))
                .setHeader("nameMatters", constant(arp.nameMatters()))
                .setHeader("client", constant("Wretched"))
                .autoStartup(arp.isAutoStart() || arp.shouldAutoStartThisRoute())
                .to("direct:split");
    }
    //@formatter:on

    private String getSftpStartEndpoint() {
        return new StringBuilder()
                .append("sftp://").append(arp.getSftpUser()).append("@").append(arp.getSftpHost()).append("/")
                .append(arp.getSftpPath())
                .append("?password=").append(arp.getSftpPassword())
                .append("&scheduler=spring&scheduler.cron=").append(arp.getRouteSchedule())
                .append("&readLock=changed&readLockMinAge=300000")
                .append("&streamDownload=true&stepwise=false")
                .append("&timeUnit=MINUTES")
                .append("&noop=").append(arp.shouldMoveFromFtp())
                .append("&move=").append(arp.getArchiveDestination())
                .append("&include=").append(arp.getWretchedBillZipRegex())
                .toString();
    }
}

我注意到这会在多重期望下通过:

mockConvert.expectedMessageCount(0); mockConvert.expectedMessageCount(4);

只有当我期望的消息比我产生的消息多时,它才会失败,例如,

mockConvert.expectedMessageCount(5);

所以 1) 考虑到“包含”正则表达式中的不匹配,为什么存根选项不排除我通过制作者发送的 所有 文件,以及2)为什么多重期望通过?顺便说一句,如果有更好的方法在没有测试容器的情况下测试现有的 sftp 消费者端点,请告诉我或指点我。

我只知道你第二个问题的答案:

2

MockEndpoint.expectedMessageCount(i) 仅确保收到 i 条消息。一旦达到消息计数,它就会认为期望得到满足。不考虑任何无关的消息。快速浏览一下 documentation 说明您可以使用 setAssertPeriod(l) 强制执行预期的消息计数,即使在该时间段之后也是如此。 5 没有通过的原因是端点从未收到第五条消息。