How to stop @CucumberContextConfiguration with @SpringBootTest from reloading application context between every test?

huangapple go评论59阅读模式
英文:

How to stop @CucumberContextConfiguration with @SpringBootTest from reloading application context between every test?

问题

我遇到了一个问题,我的应用程序上下文在每次测试之间重新加载。我正在使用功能测试属性、wiremock等将我的实际应用程序与功能测试环境进行连接。测试一直都运行得很好,但现在我们添加了几个测试,由于每次重新运行Spring应用程序,测试变得非常慢。我在我的pom中使用的io.cucumber版本为cucumber-spring、cucumber-java、cucumber-junit的7.11.1版本。

我的功能测试运行器被注解如下:

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "classpath:functional/features",
    glue = {"com.iggroup.ds.functional.stepdefinitions"},
    monochrome = true,
    tags = "@FunctionalTest",
    plugin = {"pretty", "html:target/cucumber-html-report", "junit:target/cucumber-xml-report.xml"}
)
public class FunctionalTestRunner {

    @BeforeClass
    public static void beforeClass() {
        prepareEnvironment();
    }

    private static void prepareEnvironment() {
        int applicationPort = SocketUtils.findAvailableTcpPort();
        System.setProperty("server.port", String.valueOf(applicationPort));
        System.setProperty("spring.active.profiles", "FUNCTIONAL_TEST");
        System.setProperty("spring.cloud.config.enabled", "false");
        System.setProperty("spring.cloud.config.server.bootstrap", "false");
    }
}

在我的glue包内,Cucumber配置如下:

@AutoConfigureWireMock(port = 8089)
@CucumberContextConfiguration
@SpringBootTest(
    classes = {
        ServiceApplication.class,
        RestClients.class
    },
    webEnvironment = DEFINED_PORT,
    properties = {
        "spring.profiles.active=FUNCTIONAL_TEST",
        "spring.cloud.config.enabled=false"
    }
)
public class FunctionalTestSpringCucumberConfiguration {
}

最后,应用程序本身如下:

@EnableAsync
@EnableCaching
@EnableConfigServer
@SpringBootApplication
@EnableConfigurationProperties
public class ServiceApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
    }
}

我之前在某个地方看到过,@MockBean的存在会导致上下文之间的意外刷新,尽管我从未找出为什么会这样,但我并没有定义任何@MockBean。据我所知,在我阅读的文章中,这不应该在每个场景之间刷新我的上下文,所以想知道是否有任何方法可以强制它不在每个场景之间重新连接ServiceApplication.class?

英文:

I've got this problem where my application context is reloaded between every test. I'm wiring in my actual application with functional test properties, wiremock etc. to create a functional test environment. Tests have always run fine but now we've added several it's become painfully slow due to the spring application being re-run everytime. The io.cucumber versions I'm using in my pom for cucumber-spring, cucumber-java, cucumber-junit is 7.11.1.
My Functional Test runner is annotated like this:

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "classpath:functional/features",
    glue = {"com.iggroup.ds.functional.stepdefinitions"},
    monochrome = true,
    tags = "@FunctionalTest",
    plugin = {"pretty", "html:target/cucumber-html-report", "junit:target/cucumber-xml-report.xml"}
)
public class FunctionalTestRunner {

    @BeforeClass
    public static void beforeClass() {
        prepareEnvironment();
    }

    private static void prepareEnvironment() {
        int applicationPort = SocketUtils.findAvailableTcpPort();
        System.setProperty("server.port", String.valueOf(applicationPort));
        System.setProperty("spring.active.profiles", "FUNCTIONAL_TEST");
        System.setProperty("spring.cloud.config.enabled", "false");
        System.setProperty("spring.cloud.config.server.bootstrap", "false");
    }
}

Inside my glue package the Cucumber Configuration looks like this:

@AutoConfigureWireMock(port = 8089)
@CucumberContextConfiguration
@SpringBootTest(
    classes = {
        ServiceApplication.class,
        RestClients.class
    },
    webEnvironment = DEFINED_PORT,
    properties = {
        "spring.profiles.active=FUNCTIONAL_TEST",
        "spring.cloud.config.enabled = false"
    }
)
public class FunctionalTestSpringCucumberConfiguration {
}

And lastly the application itself looks like this:

@EnableAsync
@EnableCaching
@EnableConfigServer
@SpringBootApplication
@EnableConfigurationProperties
public class ServiceApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
    }
}

I had read somewhere before that the presence of @MockBean was causing unexpected refreshes between context although I never found out as to why - but I have none defined. As far as I can tell across the articles I've been reading, this shouldn't refresh my context every time so wondering if there's any way I can force it not to rewire the ServiceApplication.class in between every scenario?

答案1

得分: 0

@AutoConfigureWireMock(port = 8089)

通过在固定端口上使用WireMock,你会使应用程序上下文变脏。这意味着每个测试将会创建一个新的应用程序上下文。负责此操作的代码会在日志中打印一个警告信息。

if (portIsFixed(testContext)) {
	if (log.isWarnEnabled()) {
		log.warn("您已经使用了固定端口进行WireMock设置 - 将会标记上下文为脏。请尽量使用随机端口,这样您的测试将会更快、更可靠,此警告将会消失");
	}
	testContext.markApplicationContextDirty(DirtiesContext.HierarchyMode.EXHAUSTIVE);
}
英文:
@AutoConfigureWireMock(port = 8089)

By using Wiremock on fixed port you are dirtying the application context. This means a new application context will be created for each test. The code responsible for this prints a warning that you can see in your logs.

if (portIsFixed(testContext)) {
	if (log.isWarnEnabled()) {
		log.warn("You've used fixed ports for WireMock setup - "
			+ "will mark context as dirty. Please use random ports, as much "
			+ "as possible. Your tests will be faster and more reliable and this "
			+ "warning will go away");
	}
	testContext.markApplicationContextDirty(DirtiesContext.HierarchyMode.EXHAUSTIVE);
}

huangapple
  • 本文由 发表于 2023年2月6日 19:02:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75360474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定