如何解决java.lang.IllegalStateException: Failed to load ApplicationContext错误。

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

How to resolve java.lang.IllegalStateException: Failed to load ApplicationContext error

问题

I have a config class with below bean creation in that

@Bean
public Subscriber consumeMessage() {
    LOGGER.debug("Subscriber bean created");
    //here is some custom logic and as it does not find actual credential file its giving error and failed to create bean at app start.

    return subscriber;
}

Looks like spring is trying to create and load all beans before running unit test and above bean creation is failing due to some business logic.

Note: Its pure Spring based app not spring-boot

java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:145) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104) [testng-6.10.jar:na]
	at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515) [testng-6.10.jar:na]
	at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:217) [testng-6.10.jar:na]
	at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:144) [testng-6.10.jar:na]
	at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169) [testng-6.10.jar:na]
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108) [testng-6.10.jar:na]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_362]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_362]
	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'consumeMessage' defined in com.teams.docu.config.GcpPubSubConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.google.cloud.pubsub.v1.Subscriber]: Factory method 'consumeMessage' threw exception; nested exception is BusinessServiceException [details=ExceptionDetails [type=AUTHENTICATION_EXCEPTION, severity=ERROR, errorcode=gcp.credentials.read.error, args=null, validationErrors=null, namedParameters=[]]]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContext

<details>
<summary>英文:</summary>

I have a config class with below bean creation in that

    @Bean
    public Subscriber consumeMessage() {
        LOGGER.debug( &quot;Subscriber bean created&quot; );
        //here is some custom logic and as it does not find actual credential file its giving error and failed to create bean at app start.

        return subscriber;
    }

Looks like spring is trying to create and load all beans before running unit test and above bean creation is failing due to some business logic.

Note: Its pure Spring based app not spring-boot

        java.lang.IllegalStateException: Failed to load ApplicationContext
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:145) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
    	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
    	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104) [testng-6.10.jar:na]
    	at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515) [testng-6.10.jar:na]
    	at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:217) [testng-6.10.jar:na]
    	at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:144) [testng-6.10.jar:na]
    	at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169) [testng-6.10.jar:na]
    	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108) [testng-6.10.jar:na]
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_362]
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_362]
    	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;consumeMessage&#39; defined in com.teams.docu.config.GcpPubSubConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.google.cloud.pubsub.v1.Subscriber]: Factory method &#39;consumeMessage&#39; threw exception; nested exception is BusinessServiceException [details=ExceptionDetails [type=AUTHENTICATION_EXCEPTION, severity=ERROR, errorcode=gcp.credentials.read.error, args=null, validationErrors=null, namedParameters=[]]]
    	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:275) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:243) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	... 18 common frames omitted
    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.google.cloud.pubsub.v1.Subscriber]: Factory method &#39;consumeMessage&#39; threw exception; nested exception is BusinessServiceException [details=ExceptionDetails [type=AUTHENTICATION_EXCEPTION, severity=ERROR, errorcode=gcp.credentials.read.error, args=null, validationErrors=null, namedParameters=[]]]
    	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	... 36 common frames omitted
    Caused by: com.teams.docu.exception.BusinessServiceException: GCP Credential cannot be created from the stream
    	at com.teams.docu.service.util.GCPUtil.getGoogleCredentials(GCPUtil.java:89) ~[classes/:na]
    	at com.teams.docu.config.GcpPubSubConfiguration.getSubscriber(GcpPubSubConfiguration.java:54) ~[classes/:na]
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
    	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
    	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	... 37 common frames omitted
    Caused by: java.io.FileNotFoundException: dummyFileLocation (No such file or directory)
    	at java.io.FileInputStream.open0(Native Method) ~[na:1.8.0_362]
    	at java.io.FileInputStream.open(FileInputStream.java:195) ~[na:1.8.0_362]
    	at java.io.FileInputStream.&lt;init&gt;(FileInputStream.java:138) ~[na:1.8.0_362]
    	at java.io.FileInputStream.&lt;init&gt;(FileInputStream.java:93) ~[na:1.8.0_362]
    	at com.teams.docu.service.util.GCPUtil.getGoogleCredentials(GCPUtil.java:87) ~[classes/:na]
    	... 49 common frames omitted

 
How to skip/mock the @Configuration class @Bean creation in spring while running unit test.

Updates: I have tried with @ContextConfiguration and below is my test class that I can update

        @ContextConfiguration(classes = GcpPubSubConfig.class)
    public class ServiceImplTest
        extends AbstractTestService&lt;TService&gt; {
    }
        
Below is framework/common class that we are using while writing unit test that I cant change.

        @ContextConfiguration(locations = {
        &quot;classpath:docu-service.xml&quot;
    })
    public abstract class AbstractTestService&lt;T&gt;
        extends AbstractTestNGSpringContextTests {
}

 but getting following error as the the framework we are using(AbstractTestService) its already using @ContextConfiguration with locations

            java.lang.IllegalStateException: Failed to load ApplicationContext
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:145) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
    	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
    	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104) [testng-6.10.jar:na]
    	at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515) [testng-6.10.jar:na]
    	at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:217) [testng-6.10.jar:na]
    	at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:144) [testng-6.10.jar:na]
    	at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169) [testng-6.10.jar:na]
    	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108) [testng-6.10.jar:na]
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_362]
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_362]
    	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
    Caused by: java.lang.IllegalStateException: Neither GenericXmlContextLoader nor AnnotationConfigContextLoader supports loading an ApplicationContext from [MergedContextConfiguration@7ea731f8 testClass = ServiceImplTest, locations = &#39;{classpath:docu-service.xml}&#39;, classes = &#39;{class com.docu.analytic.service.impl.GcpPubSubConfig}&#39;, contextInitializerClasses = &#39;[]&#39;, activeProfiles = &#39;{}&#39;, propertySourceLocations = &#39;{}&#39;, propertySourceProperties = &#39;{}&#39;, contextCustomizers = set[[empty]], contextLoader = &#39;org.springframework.test.context.support.DelegatingSmartContextLoader&#39;, parent = [null]]: declare either &#39;locations&#39; or &#39;classes&#39; but not both.
    	at org.springframework.util.Assert.state(Assert.java:94) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:233) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
    	... 18 common frames omitted
    Tests run: 5, Failures: 1, Errors: 0, Skipped: 4, Time elapsed: 2.019 sec &lt;&lt;&lt; FAILURE! - in com.docu.analytic.service.impl.ServiceImplTest
    springTestContextPrepareTestInstance(com.docu.analytic.service.impl.ServiceImplTest)  Time elapsed: 1.955 sec  &lt;&lt;&lt; FAILURE!
    java.lang.IllegalStateException: Failed to load ApplicationContext
    Caused by: java.lang.IllegalStateException: Neither GenericXmlContextLoader nor AnnotationConfigContextLoader supports loading an ApplicationContext from [MergedContextConfiguration@7ea731f8 testClass = ServiceImplTest, locations = &#39;{classpath:docu-service.xml}&#39;, classes = &#39;{class com.docu.analytic.service.impl.GcpPubSubConfig}&#39;, contextInitializerClasses = &#39;[]&#39;, activeProfiles = &#39;{}&#39;, propertySourceLocations = &#39;{}&#39;, propertySourceProperties = &#39;{}&#39;, contextCustomizers = set[[empty]], contextLoader = &#39;org.springframework.test.context.support.DelegatingSmartContextLoader&#39;, parent = [null]]: declare either &#39;locations&#39; or &#39;classes&#39; but not both.

Updates: I have updated my test class as below and I am able to resolve the **&quot;declare either &#39;locations&#39; or &#39;classes&#39; but not both&quot;** error

        @Import(GcpPubSubConfig.class)
    public class ServiceImplTest
        extends AbstractTestService&lt;GreenButtonConnectService&gt; {

</details>


# 答案1
**得分**: 1

第一种方法是使用`Mockito`来模拟一个有问题的bean例如

```java
@ExtendWith(MockitoExtension.class)
@ContextConfiguration(classes = {/** 你的配置类 **/})
class SomeTest {

    @Mock
    private Subscriber subscriber;
    
    // 测试代码在这里
}

这是最简单的示例。如果你的bean被注入到其他你想要测试的bean中,这将需要额外的测试操作,例如使用@InjectMocks或更复杂的操作。

第二种方法是使用测试上下文配置来更改bean创建代码,例如:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {/** 你的配置类 **/, SomeTest.TestConfiguration.class})
class SomeTest {

    @Configuration
    public static class TestConfiguration {

        @Bean
        public Subscriber consumeMessage() {
            // 这里包含一些虚拟测试构建逻辑
            return subscriber;
        }
    }

    @Autowired
    private Subscriber subscriber;

    // 测试代码在这里
}

为了演示这些能力,我在我的github上推送了一个可工作的示例。

英文:

If you are using pure spring without boot you can still have two options.

The first one is to use Mockito to mock a problematic bean, for example:

@ExtendWith(MockitoExtension.class)
@ContextConfiguration(classes = {/** your configuration class **/})
class SomeTest {
@Mock
private Subscriber subscriber;
// tests are here
}

This is the simplest example. If your bean is injected into another beans that you want to test, this will require additional manipulations of the test, such as using @InjectMocks or more complex things.

The second one is to use a test context configuration to change bean creation code, for example:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {/** your configuration class **/, SomeTest.TestConfiguration.class})
class SomeTest {
@Configuration
public static class TestConfiguration {
@Bean
public Subscriber consumeMessage() {
// some dummy test building logic is here
return subscriber
}
}
@Autowired
private Subscriber subscriber;
// tests are here
}

To demonstrate these abilities, I pushed a working example on my github

答案2

得分: 0

当你运行单元测试时,Spring会尝试完全初始化程序上下文。但你有几种方法可以影响Spring将要初始化的内容。

第一种方式是使用@MockBean注解,例如:

@SpringBootTest
class SomeTest {

    @MockBean
    private Subscriber subscriber;
    
    // 测试代码在这里
}

但有很多问题需要考虑,例如其他bean如何与模拟bean互动。为了解决与此相关的一些问题,可以使用Mockito

第二种方式是使用@TestConfiguration,例如:

@SpringBootTest
class SomeTest {

    @TestConfiguration
    public static class CustomConfiguration {
    
        @Bean
        public Subscriber consumeMessage() {
            // 这里包含一些虚拟测试构建逻辑
            return subscriber;
        }
    }
    
    @Autowired
    private Subscriber subscriber;
    
    // 测试代码在这里
}

如果使用测试配置,你可以自由创建Subscriber bean。但这种方式需要添加额外的配置:spring.main.allow-bean-definition-overriding=true。你可以将这行配置放入可以放在测试资源中的application.properties文件中。

选择权在你手中,哪种方法更适合你。为了演示这些方法,我在我的GitHub上上传了一个可工作的示例。

英文:

When you run a unit test Spring tries to initialize a program context completely. But you have several ways to influence what Spring will initialize.

The first way is to use the @MockBean annotation, for example:

@SpringBootTest
class SomeTest {
@MockBean
private Subscriber subscriber;
// tests are here
}

But there are a lot of things that you think about, e.g. how the other beans will be interract with mock bean. To solve some problems related to this, Mockito can be used.

The second way is to use @TestConfiguration, for example:

@SpringBootTest
class SomeTest {
@TestConfiguration
public static class CustomConfiguration {
@Bean
public Subscriber consumeMessage() {
// some dummy test building logic is here
return subscriber
}
}
@Autowired
private Subscriber subscriber;
// tests are here
}

If you use a test configuration you will be able to do whatever you want to create the Subscriber bean. But this way requires adding additional configuration: spring.main.allow-bean-definition-overriding=true. You can put this line in the application.properties that can be placed in the test reources.

The choice is yours, which of these methods will suit better. And to demonstrate these methods, I've pushed a working example on my github.

答案3

得分: 0

一种选择是可能重写单元测试,使其仅测试特定类,即无需创建应用程序上下文。另一个建议是通过使用 @MockBean 注解向测试应用程序上下文添加模拟的 Subscriber bean,例如:

@MockBean
Subscriber subscriberMock;

@MockBean JavaDoc复制的内容:

> 当按类型注册时,上下文中的任何现有匹配类型的单个bean(包括子类)都将被模拟对象替代。

英文:

One option is to potentially rewrite the unit test such that it only tests a specific class, i.e. without creating an application context. Another suggestion is to add a mocked Subscriber bean to the test application context by using @MockBean annotation, e.g.

@MockBean
Subscriber subscriberMock;

Copied from the @MockBean JavaDoc:

> When registered by type, any existing single bean of a matching type (including subclasses) in the context will be replaced by the mock.

huangapple
  • 本文由 发表于 2023年7月31日 19:17:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803098.html
匿名

发表评论

匿名网友

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

确定