Spring @DirtiesContext Annotation Example

0

In this article we will see an example of spring @DirtiesContext annotation. @DirtiesContext is a spring test annotation which is used to indicate that the application context cached should be removed and reloaded after each test run. The application context removed will also be closed.
@DirtiesContext can be declared at method level as well as class level.

@DirtiesContext Flow

If the test method is annotated with @DirtiesContext or if the test class is annotated with @DirtiesContext with classMode set to ClassMode.AFTER_EACH_TEST_METHOD, then the application context of the test context will be marked as dirty and closed.

If @DirtiesContext is declared at class level with classMode set to ClassMode.AFTER_CLASS then the application context will be closed after all the tests of the test class are run.

DirtiesContext Flow

DirtiesContext Flow

Example without @DirtiesContext

In our example will use an employee bean which will auto-wire then use the auto-wired bean in each test case. If we have not used @DirtiesContext annotation then we will have have one employee bean which will be shared by all test cases.

Employee:

package com.javarticles.spring;

import org.springframework.context.annotation.Configuration;

@Configuration
public class Employee {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "Employee(" + name + ")";
    }
}

Here is a test class without the use of @DirtiesContext.

WithoutDirtiesContextTest:

package com.javarticles.spring;


import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class WithoutDirtiesContextTest {
    @Autowired
    protected Employee emp;

    @Before
    public void beforeTest() {
        System.out.println("beforeTest: " + emp);
        emp.setName("Roy");
    }

    @Test
    public void emp1Test() {
        System.out.println("emp1Test: " + emp);
    }

    @Test
    public void emp2Test() {
        System.out.println("emp2Test " + emp);
        emp.setName("Sam");
    }
    
    @Test
    public void emp3Test() {
        System.out.println("emp3Test " + emp);
        emp.setName("Kim");
    }

    @Test
    public void emp4Test() {
        System.out.println("emp4Test " + emp);
        emp.setName("Rita");
    }
    
    @After
    public void afterTest() {
        System.out.println("afterTest: " + emp);
    }

    @Configuration
    @ComponentScan("com.javarticles.spring")
    static class Config {

    }
}

All the tests use the same employee instance as you can see employee name set in emp3Test() and the one fetched in the before method for the next test run are the same.

Output:

Mar 09, 2016 9:55:43 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@22f71333: startup date [Wed Mar 09 21:55:43 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp1Test: Employee(Roy)
afterTest: Employee(Roy)
beforeTest: Employee(Roy)
emp2Test Employee(Roy)
afterTest: Employee(Sam)
beforeTest: Employee(Sam)
emp3Test Employee(Roy)
afterTest: Employee(Kim)
beforeTest: Employee(Kim)
emp4Test Employee(Roy)
afterTest: Employee(Rita)

@DirtiesContext at Test Level

If we annotate a test method with @DirtiesContext then the context will be closed and removed from the cache after the test’s run. The context will be reloaded before the start of the next test.

WithDirtiesContextTest:

package com.javarticles.spring;


import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class WithDirtiesContextTest {
    @Autowired
    protected Employee emp;

    @Before
    public void beforeTest() {
        System.out.println("beforeTest: " + emp);
        emp.setName("Roy");
    }

    @Test
    @DirtiesContext
    public void emp1Test() {
        System.out.println("emp1Test: " + emp);
    }

    @Test
    @DirtiesContext
    public void emp2Test() {
        System.out.println("emp2Test " + emp);
        emp.setName("Sam");
    }
    
    @Test
    public void emp3Test() {
        System.out.println("emp3Test " + emp);
        emp.setName("Kim");
    }
    
    @Test
    public void emp4Test() {
        System.out.println("emp4Test " + emp);
        emp.setName("Rita");
    }

    @After
    public void afterTest() {
        System.out.println("afterTest: " + emp);
    }

    @Configuration
    @ComponentScan("com.javarticles.spring")
    static class Config {

    }
}

emp1Test() and emp2Test() tests are annotated with @DirtiesContext. After the test is run, the context is closed and removed from cache. emp3Test() and emp4Test() doesn’t have @DirtiesContext so ended up reusing the same employee bean.

Output:

Mar 09, 2016 9:56:10 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@3fb6a447: startup date [Wed Mar 09 21:56:10 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp1Test: Employee(Roy)
afterTest: Employee(Roy)
Mar 09, 2016 9:56:10 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@3fb6a447: startup date [Wed Mar 09 21:56:10 IST 2016]; root of context hierarchy
Mar 09, 2016 9:56:10 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@10e92f8f: startup date [Wed Mar 09 21:56:10 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp2Test Employee(Roy)
afterTest: Employee(Sam)
Mar 09, 2016 9:56:10 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@10e92f8f: startup date [Wed Mar 09 21:56:10 IST 2016]; root of context hierarchy
Mar 09, 2016 9:56:10 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@635eaaf1: startup date [Wed Mar 09 21:56:10 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp3Test Employee(Roy)
afterTest: Employee(Kim)
beforeTest: Employee(Kim)
emp4Test Employee(Roy)
afterTest: Employee(Rita)
Mar 09, 2016 9:56:10 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@635eaaf1: startup date [Wed Mar 09 21:56:10 IST 2016]; root of context hierarchy

@DirtiesContext at Class Level

You can also declare @DirtiesContext at class level. You can use classMode attribute to define when to mark the context as dirty. In our example, we have set it to ClassMode.AFTER_EACH_TEST_METHOD so that the associated context is marked as dirty after each test method in the class. If it is set to ClassMode.AFTER_CLASS, it will marked as dirty after the test class.

ClassLevelDirtiesContextTest:

package com.javarticles.spring;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class ClassLevelDirtiesContextTest {
    @Autowired
    protected Employee emp;

    @Before
    public void beforeTest() {
        System.out.println("beforeTest: " + emp);
        emp.setName("Roy");
    }

    @Test
    public void emp1Test() {
        System.out.println("emp1Test: " + emp);
    }

    @Test
    public void emp2Test() {
        System.out.println("emp2Test " + emp);
        emp.setName("Sam");
    }

    @Test
    public void emp3Test() {
        System.out.println("emp3Test " + emp);
        emp.setName("Kim");
    }

    @Test
    public void emp4Test() {
        System.out.println("emp4Test " + emp);
        emp.setName("Rita");
    }
    
    @After
    public void afterTest() {
        System.out.println("afterTest: " + emp);
    }

    @Configuration
    @ComponentScan("com.javarticles.spring")
    static class Config {

    }
}

Output:

Mar 09, 2016 9:53:58 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@79b4d0f: startup date [Wed Mar 09 21:53:58 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp1Test: Employee(Roy)
afterTest: Employee(Roy)
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@79b4d0f: startup date [Wed Mar 09 21:53:58 IST 2016]; root of context hierarchy
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@10e92f8f: startup date [Wed Mar 09 21:53:59 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp2Test Employee(Roy)
afterTest: Employee(Sam)
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@10e92f8f: startup date [Wed Mar 09 21:53:59 IST 2016]; root of context hierarchy
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@635eaaf1: startup date [Wed Mar 09 21:53:59 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp3Test Employee(Roy)
afterTest: Employee(Kim)
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@635eaaf1: startup date [Wed Mar 09 21:53:59 IST 2016]; root of context hierarchy
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@1afd44cb: startup date [Wed Mar 09 21:53:59 IST 2016]; root of context hierarchy
beforeTest: Employee(null)
emp4Test Employee(Roy)
afterTest: Employee(Rita)
Mar 09, 2016 9:53:59 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@1afd44cb: startup date [Wed Mar 09 21:53:59 IST 2016]; root of context hierarchy

Download the source code

This was an example about spring @DirtiesContext Annotation.

You can download the source code here: springDirtiesContextExamples.zip

About Author

Ram's expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring. You can reach him at rsatish.m@gmail.com

Comments are closed.