spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
55.39k stars 37.67k forks source link

ApplicationContext fails to load in TestNG test if previous test is annotated with @DirtiesContext [SPR-12918] #17517

Closed spring-projects-issues closed 5 years ago

spring-projects-issues commented 9 years ago

David Blake opened SPR-12918 and commented

Upgrading from Spring Framework 4.0.5 to 4.1.6 (or 4.1.0) causes Test class #2 to fail with the following exception if Test class #1 is annotated with @DirtiesContext at the class level (see example code in the comments section for details).

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.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:145)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:138)
    at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:175)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:107)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerContext': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.hp.ipg.framework.config.amqp.AmqpFrameworkConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.queue.RabbitMQManagementClient com.hp.ipg.framework.config.amqp.AmqpFrameworkConfig.rabbitMQManagementClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rabbitMQManagementClient': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.HttpClientFactory com.hp.ipg.framework.client.Client.httpClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpClientFactoryUntrusted': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
    ... 29 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.hp.ipg.framework.config.amqp.AmqpFrameworkConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.queue.RabbitMQManagementClient com.hp.ipg.framework.config.amqp.AmqpFrameworkConfig.rabbitMQManagementClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rabbitMQManagementClient': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.HttpClientFactory com.hp.ipg.framework.client.Client.httpClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpClientFactoryUntrusted': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:368)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:523)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:512)
    at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:227)
    at org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeanOfType(BeanFactoryAnnotationUtils.java:80)
    at org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeanOfType(BeanFactoryAnnotationUtils.java:56)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineQualifiedTransactionManager(TransactionAspectSupport.java:377)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:361)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:271)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:70)
    at com.hp.ipg.services.SchedulerService.deletePriorBuildTriggersAndJobs(SchedulerService.java:119)
    at com.hp.ipg.services.config.SchedulerContext.configureTriggerAndJobState(SchedulerContext.java:51)
    at com.hp.ipg.services.config.SchedulerContext.init(SchedulerContext.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:349)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:300)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
    ... 46 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.queue.RabbitMQManagementClient com.hp.ipg.framework.config.amqp.AmqpFrameworkConfig.rabbitMQManagementClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rabbitMQManagementClient': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.HttpClientFactory com.hp.ipg.framework.client.Client.httpClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpClientFactoryUntrusted': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 81 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rabbitMQManagementClient': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.HttpClientFactory com.hp.ipg.framework.client.Client.httpClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpClientFactoryUntrusted': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:496)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$100(AutowiredAnnotationBeanPostProcessor.java:115)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:526)
    ... 83 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.hp.ipg.framework.HttpClientFactory com.hp.ipg.framework.client.Client.httpClient; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpClientFactoryUntrusted': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 93 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpClientFactoryUntrusted': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:496)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$100(AutowiredAnnotationBeanPostProcessor.java:115)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:526)
    ... 95 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.core.env.Environment com.hp.ipg.framework.HttpClientFactory.env; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 103 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1168)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:496)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$100(AutowiredAnnotationBeanPostProcessor.java:115)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:526)
    ... 105 more

Affects: 4.1 GA

Issue Links:

Referenced from: commits https://github.com/spring-projects/spring-framework/commit/3c5a9b4e1d302b789fcad45a1f75715618dff0e7

spring-projects-issues commented 9 years ago

Sam Brannen commented

I'm afraid the supplied stack trace does not provide much to go on, other than the fact that you are using TestNG.

Can you please provide the details of your setup?

Are tests #1 and #2 different test classes or different test methods within the same class?

Have you tried a different version of Spring, for example 4.1.0?

Where is @DirtiesContext applied, at the method level or class level and on which method/class?

Exactly which TestExecutionListener classes are configured for your test class (and all of its parent classes)? In other words, please provide every declaration of @TestExecutionListeners in the affected test class hierarchy.

Thanks for any feedback you can provide!

Sam

spring-projects-issues commented 9 years ago

Sam Brannen commented

In any case, without knowing the details of your configuration, it sounds like you might be closing the ApplicationContext programmatically which is not supported.

The reason I suspect this is that a NoSuchBeanDefinitionException with the message "No bean named 'environment' is defined" is thrown whenever an attempt is made to autowire an object (e.g., your test instance) using a closed ApplicationContext.

See my comments here for details.

Of course, I cannot verify this assumption without seeing your test code. So please confirm whether you are closing the context programmatically.

Thanks,

Sam

spring-projects-issues commented 9 years ago

David Blake commented

The Test #1 and test #2 are different test classes in separate source files. Test class #1 is annotated with @DirtiesContext at the class level. I need that due to using mokito mocks in test class #1 and therefore want Test class #2 context to be regenerated.

I am not explicitly closing the ApplicationContext programmaticall, just using @DirtyContext in Test class #1.

spring-projects-issues commented 9 years ago

David Blake commented

I can try going back from 4.1.6 until I see which version the issue came in on if that is helpful. I will try the 4.1.0 you suggested first.

spring-projects-issues commented 9 years ago

Sam Brannen commented

OK. Thanks for the feedback. I'll see if I can reproduce the issue.

In the meantime, if you could answer my question above regarding TestExecutionListener configuration, I'd appreciate it.

spring-projects-issues commented 9 years ago

David Blake commented

Thanks for your assistance Sam. I will get you the requested information..

spring-projects-issues commented 9 years ago

Sam Brannen commented

This is potentially related to #15172, #17012, and INT-3543.

spring-projects-issues commented 9 years ago

David Blake commented

I don't have any TestExecutionListener config items in the test code, but I do extend AbstractTestNGSpringContextTests which is authored by you I noticed.

AbstractTestNGSpringContextTests

@TestExecutionListeners({
    ServletTestExecutionListener.class,
    DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class})
public abstract class AbstractTestNGSpringContextTests implements IHookable, ApplicationContextAware {

HPUnitTest Class

@ContextConfiguration(classes = ServicesUnitTestConfig.class)
@ActiveProfiles("unit")
public abstract class HPUnitTest extends AbstractTestNGSpringContextTests {

Test Class #1

@DirtiesContext
@Test(groups = { "L1", "Service Tests", "Queue" })
public class AccountSummaryServiceTest extends HPUnitTest {

Test Class #2

@Test(groups = { "L1", "Service Tests" })
public class SchedulerServiceTest extends HPUnitTest {
spring-projects-issues commented 9 years ago

Sam Brannen commented

This issue is potentially related to #10800.

spring-projects-issues commented 9 years ago

Sam Brannen commented

Out of curiosity, what happens if you configure your three test classes as follows?

HPUnitTest Class

@ContextConfiguration(classes = ServicesUnitTestConfig.class)
@ActiveProfiles("unit")
public abstract class HPUnitTest extends AbstractTestNGSpringContextTests {

Test Class #1

@DirtiesContext
@Test(suiteName = "AccountSummaryService", groups = {"L1", "Service Tests", "Queue"})
public class AccountSummaryServiceTest extends HPUnitTest {

Test Class #2

@Test(suiteName = "SchedulerService", groups = {"L1", "Service Tests"})
public class SchedulerServiceTest extends HPUnitTest {

Note the use of unique values for suiteName.

Please let me know the outcome of your tests with the above configuration.

Cheers,

Sam

spring-projects-issues commented 9 years ago

David Blake commented

Tried the suggested changes and it failed the same way.

spring-projects-issues commented 9 years ago

David Blake commented

Rebuilt with 4.1.0 and it fails with a similar call stack though the 4.1.6 call stack has extra details logged so it looks like the trace logging was improved over time. Overall it is the same illegalStateException - Failed to load ApplicationContext error.

spring-projects-issues commented 9 years ago

Sam Brannen commented

Thanks for helping investigate.

Since those attempts failed as well, I think this issue may not be directly related to spring-test especially since there were no (or not many) changes to Spring's TestNG and @DirtiesContext support from 4.0.5 to 4.1. In any case, we will continue to investigate the cause.

spring-projects-issues commented 9 years ago

David Blake commented

Based on what we've seen so far with testing this, I'm curious what changes have happened in org.springframework.beans.factory between 4.0.5 and 4.1.0. I'm currently stepping through the working code with 4.0.5 to try and better understand what makes that work for my case. I'll also try going back to 4.1.0 and do the same there for the failing case. I'll post what I find if anything.

spring-projects-issues commented 9 years ago

David Blake commented

Here is what I'm seeing as a difference between the working 4.0.5 case and the 4.1.0 failing case.

In the stack trace in this issue's Description, notice the call to the method deletePriorBuildTriggersAndJobs(). That is ours and is annotated with @Transactional(propagation = REQUIRED). When I put a breakpoint on the method definition and step into code there is a difference for the working and non-working case.

Non-working 4.1+ case

Stepping into the call stack results in going into Spring's org.springframework.transaction package and eventually into Spring's org.springframework.beans.factory package and eventually fails.

Working 4.0.5 case

Stepping into the call stack does not go into Spring's org.springframework.transaction package but instead goes to the first line of the method deletePriorBuildTriggersAndJobs() which is ours.

Summary

It appears that 4.0.5 to 4.1+ introduces extra processing or at least different processing for @Transactional annotations that fail after a test is run with @DirtiesContext at the class level.

spring-projects-issues commented 9 years ago

Sam Brannen commented

Thank you for taking the time to perform additional analysis!

We will take your findings into account.

spring-projects-issues commented 9 years ago

Sam Brannen commented

Interim testing work has been committed in GitHub commit 3c5a9b4:

Introduce class-level @DirtiesContext tests for TestNG

Prior to this commit, ClassLevelDirtiesContextTests existed for verifying the expected behavior of @DirtiesContext declared at the class level in conjunction with JUnit and SpringJUnit4ClassRunner.

This commit introduces analogous tests for TestNG in the new ClassLevelDirtiesContextTestNGTests class.

Furthermore, ContextCacheTestUtils and TrackingTestNGTestListener have been introduced to reduce code duplication across the test suite.

spring-projects-issues commented 9 years ago

Sam Brannen commented

This issue is potentially related to #15166, in the sense that parallel construction of an application context results in a null Environment being autowired into an @Configuration class.

spring-projects-issues commented 9 years ago

David Blake commented

I see that version 4.1.7 is due around May 20th. Do we currently know if a fix for this issue will be possible by that date?

spring-projects-issues commented 9 years ago

David Blake commented

Update to previous comment. Version 4.1.7 has been pushed out to mid July according to the dashboard. I am still interested in a fix for this issue and currently don't have a way to work around this. Let me know if I can help assist with anything.

spring-projects-issues commented 9 years ago

Juergen Hoeller commented

So with 4.0.5, it looks like your @Transactional rule on deletePriorBuildTriggersAndJobs() hasn't kicked in at all before, despite your use of the AspectJ transaction aspect. That actually seems like a bug in its own right... As of 4.1, for some reason, the transaction processing does kick in as requested. So for that part, I'd rather declare 4.0.5 at fault and 4.1 to be correct. From that perspective, does it work for you if you remove the @Transactional declaration completely?

Now, with the transaction actually kicking in there, it tries to resolve a transaction manager and apparently encounters an incompletely initialized ApplicationContext. This may happen on startup as well as on shutdown, but it's more likely to happen for access after shutdown... Is there possibly some asynchronous task involved, trying to access the context after its shutdown? Or some concurrent test runs that interfere in terms of the state of a shared ApplicationContext?

Juergen

spring-projects-issues commented 9 years ago

David Blake commented

From that perspective, does it work for you if you remove the @Transactional declaration completely?

Yes, if I remove the @Transactional it works. It also works if I remove the @DirtiesContext from around Test class #1.

Is there possibly some asynchronous task involved, trying to access the context after its shutdown? Or some concurrent test runs that interfere in terms of the state of a shared ApplicationContext?

There is nothing, I know of, that our code is doing to either close the ApplicationContext or asynchronously access the context. The failure is not happening during a specific Test but instead during what appears to be the initialization of the second Test class in preparation for running the second group of Test. The first Test class has the @DirtiesContext. When it completes doesn't that annotation cause the ApplicationContext to be reset? Then when it starts the second test class processing it causes the ApplicationContext to be reloaded, I believe, even before starting to execute our tests that are part of the second class.

Does this answer your questions completely? I'd be happy to expand further.

spring-projects-issues commented 9 years ago

David Blake commented

Removing the reference to the bean, Environment, that is the cause of the failure to load the ApplicationContext also fixes the issue and could be a possible workaround for us if we can replace that functionality with something else.

Seems the failure of the Environment has been an issue in the past and is curiously the only bean of around 300 that get loaded in our system that is a problem currently. Just an observation.

import org.springframework.core.env.Environment; @Autowired Environment env;

spring-projects-issues commented 9 years ago

Sam Brannen commented

There is nothing, I know of, that our code is doing to either close the ApplicationContext or asynchronously access the context.

That's odd, because it really sounds like that would be the case based on the error you're encountering.

The failure is not happening during a specific Test but instead during what appears to be the initialization of the second Test class in preparation for running the second group of Test.

Again, this sounds to me like there is some overlap in the execution of the tests in terms of test execution lifecycle callbacks.

Have you tried out my unique suite name per test class proposal (see comments above) on all of your TestNG-based tests?

The first Test class has the @DirtiesContext. When it completes doesn't that annotation cause the ApplicationContext to be reset?

Yes, the corresponding ApplicationContext should be closed after such a test class has completed.

Then when it starts the second test class processing it causes the ApplicationContext to be reloaded, I believe, even before starting to execute our tests that are part of the second class.

That is correct, but still... it sounds like the ordering is not correct.

Could you please execute your tests with DEBUG logging enabled for the org.springframework.test.context logging category and supply us the output?

See my detailed comments in #10800 for the kind of problems that can occur if the TestNG test execution order is incorrectly configured.

Regards,

Sam

spring-projects-issues commented 9 years ago

David Blake commented

Could you please execute your tests with DEBUG logging enabled for the org.springframework.test.context logging category and supply us the output? Could you provide instructions or a link on how to enable DEBUG logging in springframework code? Is there a log4J property file or something for that?

Have you tried out my unique suite name per test class proposal (see comments above) on all of your TestNG-based tests? Yes I documented that in a previous comment. Fails with the same stack trace. I have minimized the failure case down to two test classes each with 8 tests. I am going to further minimize it down to just two test classes and two test methods. Would this help with your concern about order? Anyway, less is better for failure reproduction imho.

One thing further. I can see in the spring tools UI while I'm running the tests that the first test class completes all 8 tests successfully and the call stack shows it going into testing code to initialize the context. During this the beans are reloaded, there are ~300 in my projects, and it always fails trying to lookup the Environment springframework bean which is autowired into one of our classes. The failure occurs "before" test class two methods are executed. I removed this autowired reference from our code and hardcoded the values we were getting from that just for testing and everything works fine without that.

I will 1. turn on debug when I know how. and 2. will further simplify the test run needed to show the failure.

thanks for your inputs and assistance.

David Blake

spring-projects-issues commented 9 years ago

Sam Brannen commented

To enable DEBUG logging for the org.springframework.test.context category, you could create a log4j.properties (in the root of the classpath for your tests) similar to the following:

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%-5p] [%c] - %m%n

log4j.rootCategory=ERROR, console

log4j.logger.org.springframework.beans=INFO
log4j.logger.org.springframework.context=INFO
log4j.logger.org.springframework.test.context=DEBUG

If you already have log4j.properties or log4j.xml configuration in place, just adapt it accordingly.

spring-projects-issues commented 9 years ago

Sam Brannen commented

Yes I documented that in a previous comment. Fails with the same stack trace.

Yes, I recall that. ;)

This time I was asking if you declared a unique suiteName for every concrete TestNG-based test class in your application.

I have minimized the failure case down to two test classes each with 8 tests. I am going to further minimize it down to just two test classes and two test methods. Would this help with your concern about order?

YES. That would be very beneficial, especially if you can provide us a scaled down project that reproduces the issue. That way we could get our hands on something that is actually breaking and debug it ourselves.

Thanks in advance!

Sam

spring-projects-issues commented 8 years ago

David Blake commented

Our code base was modified which resulted in the removal of the Environment bean being autowired which fixes the problem we were having. Due to the complexity of our code base I was unable to get any further minimal test to duplicate the issue.

Now that we are past this we have run into another issue that follows a similar theme in that Spring Framework 4.0.5 works with TestNG and @DirtiesContext but after updating to 4.1.6 we are getting some detached entity persisting object errors with tests that worked fine in 4.0.5 and work with 4.1.6 if I remove the @DirtiesContext annotation from around the previous test class that executed.

I will submit this as a different defect unless you want it to remain part of this one.

spring-projects-issues commented 7 years ago

Sam Brannen commented

Please note that #19400 may be duplicate of this issue.

spring-projects-issues commented 5 years ago

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.