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:
- @BeforeClass
- Construcor call
- @Before
- @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
Advertisement
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);