Announcement Announcement Module
No announcement yet.
TestContextManager: ContextCache should be in a ThreadLocal Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • TestContextManager: ContextCache should be in a ThreadLocal

    Hi everyone,

    How I stumbled upon a design-flaw in TestContextManager:
    Yesterday I switched my testcases from JUnit to TestNG. I have some long-running tests, so I immediately enabled TestNG's "parallel"-Setting, so that my testcases run in a multithreaded fashion.

    After running the testcases I realized that I get a lot of Exceptions, which were caused by tests running in parallel and disturbing each other. E.g. flushing the database, etc..

    In my tests I use a inmemory-HSQLDB, so every Test should have a fresh DB and there should be no shared database server. The cause of that behaviour seems to be the ContextCache of the TestContextManager, which seems to be shared across multiple TestNG-Threads.

    I understand that you cache the internal Spring-Contexts between Tests, in order to improve speed. Nevertheless I dont think that it is a good idea to share the Cache between Threads (I'm only talking about Tests. This is different in a productive application, of course.)

    My proposal on how to improve the TestContextManager:
    When you look into the TestContextManager, you will see that the ContextCache is a static variable:
    static final ContextCache contextCache = new ContextCache();
    This causes one ContextCache to be shared between multiple Test-Threads!

    My proposal would be to make the ContextCache a ThreadLocal:
    protected static final ThreadLocal<ContextCache> contextCache = new ThreadLocal<ContextCache>();
    Therefore each Thread would have its own ContextCache.

    I was able to fix my concurrency issues with that fix. I have no unexplainable Exceptions any more. But I still have Context-caching (I dont see the Spring-container being reinitialized all the time).

    What do you think about that? I realize that this might have a impact on @Timed or @Test(threadPoolSize=>0). But we should start thinking about running Tests in parallel, nowadays where everyone has Dual- or Quadcore CPUs :-)

    kind regards,

  • #2

    Update: I noticed that I was missing something:

    In the class AbstractTestNGSpringContextTests I had to move the content of the constructor to springTestContextBeforeTestClass(). (The constructor is called by the TestNG Main-Thread and not by the ThreadPool, therefore my Threadlocal was set up by incorrectly).

    I was able to get a 30% performance-improvement in my testsuite (21 seconds instead of 29sec.). I expect the ratio to get even better as the testsuite grows (due to the extra initialization overhead of multiple threads).

    What do you think are my chances to get these changes into Spring? Any comments?