英文:
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( "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(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 '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.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.<init>(FileInputStream.java:138) ~[na:1.8.0_362]
at java.io.FileInputStream.<init>(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<TService> {
}
Below is framework/common class that we are using while writing unit test that I cant change.
@ContextConfiguration(locations = {
"classpath:docu-service.xml"
})
public abstract class AbstractTestService<T>
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 = '{classpath:docu-service.xml}', classes = '{class com.docu.analytic.service.impl.GcpPubSubConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]: declare either 'locations' or 'classes' 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 <<< FAILURE! - in com.docu.analytic.service.impl.ServiceImplTest
springTestContextPrepareTestInstance(com.docu.analytic.service.impl.ServiceImplTest) Time elapsed: 1.955 sec <<< 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 = '{classpath:docu-service.xml}', classes = '{class com.docu.analytic.service.impl.GcpPubSubConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]: declare either 'locations' or 'classes' but not both.
Updates: I have updated my test class as below and I am able to resolve the **"declare either 'locations' or 'classes' but not both"** error
@Import(GcpPubSubConfig.class)
public class ServiceImplTest
extends AbstractTestService<GreenButtonConnectService> {
</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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论