Skip to content

Sharing an Object between two Test classes in either JUnit or TestNG

Forgive the elementary question, I am learning Java still so need some advice on best practice here. I have a valid scenario where I wish to share the same object between two distinct Test classes using JUnit or TestNG. I understand that tests/test classes should not usually share state but this is a long-running journey.

I understand the JVM executes for both frameworks in this order:

  1. @BeforeClass
  2. Construcor call
  3. @Before
  4. @Test

Given I have an Person class with one field name and one getter & setter for same and I instantiate an instance of it in one Test Class:

public class FirstPersonTest {

    private Person firstPerson;

    @BeforeClass
    private void setup() {
        firstPerson = new Person("Dave");
    }

    @Test
    public void testName() {
        assertEquals("Dave", firstPerson.getName());
    }
}

And a second Test class:

public class SecondPersonTest {

    private Person firstPerson;
    private static String name;

    @BeforeClass
    private void setup(){
        name = firstPerson.getName(); //null pointer, firstPerson reference no longer exists from FirstPersonTest
    }

    @Test
    public void testName(){
        assertEquals("Dave", name);
    }
}

What is the optimal way of accessing the firstPerson object in the second class? I don’t want to instantiate it a second time because I wish to share state for a journey test.

I want to be able to pass firstPerson instance in the constructor or an annotated setup method, but don’t wish to instantiate the SecondPersonTest within the body of FirstPersonTest

Answer

You can use a singleton class for this purpose.

public class LocalStorage {
    private static volatile LocalStorage instance;
    private Map<String, Object> data = new HashMap<>();

    private LocalStorage() {
    }

    public static LocalStorage getInstance() {
        if (instance == null) {

            synchronized (LocalStorage.class) {
                if (instance == null) {
                    instance = new LocalStorage();
                }
            }
        }

        return instance;
    }

    public static void addData(String key, Object value) {
        getInstance().data.put(key, value);
    }

    public static Object getData(String key) {
        return getInstance().data.get(key);
    }

    public static <T> T getData(String key, Class<T> clazz) {
        return clazz.cast(getInstance().data.get(key));
    }
}

You can store the whole Person object or only the name field of the Person object.

To store:

Person firstPerson = new Person("Dave");
LocalStorage.addData("Dave", firstPerson);

To get it back:

Person firstPerson = LocalStorage.getData("Dave", Person.class);