gpt4 book ai didi

chalice 3 : Custom Application class for integration tests

转载 作者:行者123 更新时间:2023-12-02 11:33:39 28 4
gpt4 key购买 nike

我想自定义用于集成测试的应用程序类。根据用户指南,这应该是可能的:

The Integration annotation supports an optional applicationClass attribute which may be used to specify the application class to use for the functional test. The class must extend GrailsAutoConfiguration.

(来自 http://grails.github.io/grails-doc/3.0.x/guide/testing.html#integrationTesting )

所以我的集成测试用

注释
@Integration(applicationClass = TestApplication)
class DataServiceSpec extends Specification {

测试应用程序类(尚未自定义)如下所示:

class TestApplication extends GrailsAutoConfiguration {
}

运行集成测试(使用 grails test-app 或 gradle integrationTest 会导致 ApplicationContextException ,其根本原因是缺少 EmbeddedServletContainerFactory。这是一个错误,还是我错误地使用了 applicationClass 属性?这样一个定制的应用程序类应该驻留在哪里?当我将它放在集成测试源和 grails-app/init 中时,我遇到了同样的错误。或者是否有另一种方法可以将另一个 @Configuration 类添加到集成测试上下文中?

这是完整的堆栈跟踪:

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:49)
at org.spockframework.spring.SpringInterceptor.interceptSetupMethod(SpringInterceptor.java:42)
at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:28)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at grails.boot.GrailsApp.run(GrailsApp.groovy:49)
at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:101)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
... 24 more
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:183)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:156)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
... 32 more

最佳答案

不幸的是,创建一个扩展 GrailsAutoConfiguration 的类是不够的。对于默认的 Grails Application 类,一些 AST 转换在幕后进行,以提供应用程序运行所需的一切。总而言之,Application 类实际上看起来更像是这样的:

@EnableWebMvc
@EnableAutoConfiguration(exclude = [DataSourceAutoConfiguration, MessageSourceAutoConfiguration, ReactorAutoConfiguration])
public class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
}

@EnableAutoConfiguration 注释才是真正让事情发挥作用的东西。 Spring Boot docs描述它的作用:

Enable auto-configuration of the Spring Application Context, attempting to guess and configure beans that you are likely to need. Auto-configuration classes are usually applied based on your classpath and what beans you have defined. For example, If you have tomcat-embedded.jar on your classpath you are likely to want a TomcatEmbeddedServletContainerFactory (unless you have defined your own EmbeddedServletContainerFactory bean).

简短回答

添加缺少的注释,以便您的 TestApplication 类镜像上面的类。

长答案

Grails 3 应用程序的核心是 Spring Boot 应用程序。同样,默认 Grails Application 类公开的 main 方法负责运行应用程序,它通过调用 GrailsApp.run() 来运行。 GrailsApp 扩展了 SpringApplication,后者负责运行 Spring Boot 应用程序的繁重工作。

SpringApplication 负责创建 Spring 应用程序上下文。默认情况下,Spring Boot 创建一个 AnnotationConfigEmbeddedWebApplicationContext。如 Spring Boot documentation 中所述:

This context will create, initialize and run an EmbeddedServletContainer by searching for a single EmbeddedServletContainerFactory bean within the ApplicationContext itself.

很明显,要使其工作,需要在某处定义一个 EmbeddedServletContainerFactory。您看到的异常是因为没有找到任何异常。我们这里有两个选择。您可以执行 Grails 对默认 Application 类所做的操作并添加如上所示的 @EnableAutoConfiguration 注释,或者显式定义您自己的 EmbeddedServletContainerFactory:

@Configuration
class TestApplication extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(TestApplication, args)
}

@Bean
public EmbeddedServletContainerFactory containerFactory() {
return new TomcatEmbeddedServletContainerFactory(0)
}
}

请注意,Grails 默认情况下仅扫描与 Application 类相关的类。您可能需要通过将以下内容添加到您的 Application 类中来覆盖它:

@Override
protected boolean limitScanningToApplication() {
return false
}

关于 chalice 3 : Custom Application class for integration tests,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29652130/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com