Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When testing using JUnit 4 Suite, destroy-methods are called at the end of the test suite instead of per test [SPR-7377] #12035

Closed
spring-projects-issues opened this issue Jul 15, 2010 · 6 comments
Assignees
Labels
in: test Issues in the test module status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jul 15, 2010

John Cheng opened SPR-7377 and commented

Expected Behavior

When running multiple test classes using JUnit4's Suite runner, I expect a Spring bean's destroy-method to be called at the end of each test. In other words, I expect to see:

Start TestSuite
 Start Test1
  ... Bean.initMethod()
  ... Bean.destroyMethod()
 End Test1
 Start Test2
  ... Bean.initMethod()
  ... Bean.destroyMethod()
 End Test2
End TestSuite

This is because I need resources to be freed after Test1, so that I can cleanly re-acquire those resources when Test2 starts.

Current Behavior

A bean's init-method is called before each test. However, the destroy-method is called at the end of the test suite, in one batch. In other words,

Start TestSuite
 Start Test1
  ... Bean.initMethod()
 End Test1
 Start Test2
  ... Bean.initMethod()
 End Test2
 Bean.destroyMethod() (caused by Test2)
 Bean.destroyMethod() (caused by Test1)
End TestSuite

In the current behavior, resources acquired in Test1 will not be freed via the destroy-method when Test2 starts.

Steps to reproduce

I've attached sample code. It is in the form of an Eclipse project, but can be executed via ant:

$ ant  | grep method
jcheng@jackrabbit: ~/lms-projects/DEV_SPRING_3/Spring_Bug_Report_01 $ ant  | grep method
    [junit] method: LifeCycleBean[0].init()
    [junit] method: SampleJunitTest1.testOne()
    [junit] method: LifeCycleBean[1].init()
    [junit] method: SampleJunitTest2.testTwo()
    [junit] method: LifeCycleBean[1].destroy()
    [junit] method: LifeCycleBean[0].destroy()

Note that in the stderr output (when you run Ant), the LifeCycleBean's destroy-method is not called until the test suite ends.


Affects: 3.0.3

Attachments:

Issue Links:

2 votes, 2 watchers

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

John, have you tried annotating either your test class or test methods with @DirtiesContext?

That should give you the behavior you desire.

So please try it out and report back here with your findings.

Thanks,

Sam

@spring-projects-issues
Copy link
Collaborator Author

Conny Kreyßel commented

Why is "@DirtiesContext per test class" not the default behavior?

If i run in eclipse a folder full of spring junit4 based tests, i run out of memory because every single application context of every test class is hold in memory.

If you have hibernate/ehcache/lucene on board, you get also problems with threads that run out, because it would not shutdown it resources.

Hints?

@spring-projects-issues
Copy link
Collaborator Author

Paul Khodchenkov commented

I am also surprised that spring does not close application context after the test class. @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) helped me to force context close after the test class, otherwise context is closed only when maven-surefire-plugin finish.

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Conny,

Why is "@DirtiesContext per test class" not the default behavior?

The default behavior of the TestContext framework is to cache all application contexts within the currently executing process (i.e., typically in a test run within the IDE or a project build in Maven, Ant, Gradle, etc.).

There is good reason for this: one of the primary objectives of the TestContext is caching for faster build times.

Please see the reference manual for details:

Of course, if you have not designed your test classes to reuse the same application context (i.e., by declaring the same uniquely identifying configuration (e.g., locations, classes, etc.)), then the TestContext will create and cache a new ApplicationContext for each unique set of configuration attributes (as defined by @ContextConfiguration).

So you have two options:

  1. design your test classes so that they reuse the same configuration -- for example, by declaring abstract base test classes that are configured with @ContextConfiguration.
  2. or by annotating individual test classes with @DirtiesContext where appropriate.

I hope this helps to shed some light on the intended use cases for the TestContext framework with regard to caching of application contexts.

Regards,

Sam

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Paul,

Please see my response to Conny as it applies directly to your comments as well.

Regards,

Sam

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

I am closing this issue as Works as Designed since this reflects the intended behavior. For details, please refer to my comments regarding caching in the TestContext framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants