cjmaria
cjmaria

Reputation: 340

How to call a set-up method before certain JUnit tests

I am creating unit tests with JUnit for methods that manipulate JSON objects. I want to create a method in my test file that sets up the object that will be used in some, but not all, of my test methods. How do I selectively run the set-up method and transfer it's resulting JSONObject to the test methods? Is there a better way to do this? Here is what I was thinking for a set up method (using gson):

    public static JsonObject prepareTestJson(){
        JsonObject testJson_container = new JsonObject();
        JsonObject testJson_inner = new JsonObject();
        String ContactInfo = "+1 111 111 1111";
        testJson_inner.addProperty("Contact", ContactInfo);
        testJson_container.add("ID", testJson_inner);
        return testJson_container;
    }

Upvotes: 1

Views: 7249

Answers (1)

davidxxx
davidxxx

Reputation: 131526

How do I selectively run the set-up method and transfer it's resulting JSONObject to the test methods?

No you cannot select the test methods for which a method annotated with @Before should be applied.

Is there a better way to do this?

You could simply invoke this method before each test (you can also make it private and an instance method to reduce its access :

private JsonObject prepareTestJson(){
    JsonObject testJson_container = new JsonObject();
    JsonObject testJson_inner = new JsonObject();
    String ContactInfo = "+1 111 111 1111";
    testJson_inner.addProperty("Contact", ContactInfo);
    testJson_container.add("ID", testJson_inner);
    return testJson_container;
}

such as :

@Test
public void foo(){
  JsonObject json = prepareTestJson();
  ...
}

Another alternative is splitting your test class in two : one with the tests that require the setup() and another one with the tests that don't require it.
In this way you could use a init method with @Before or simply put these statements in the class constructor.
For example :

private JsonObject testJson_container;

@Before
public void prepareTestJson(){
    testJson_container = new JsonObject();
    JsonObject testJson_inner = new JsonObject();
    String ContactInfo = "+1 111 111 1111";
    testJson_inner.addProperty("Contact", ContactInfo);
    testJson_container.add("ID", testJson_inner);       
}

But this way is an artificial/technical split, it may make the test code less readable.
So I think that in most of cases, I would stick to the first way.


Additionally, with JUnit 5 you have an interesting workaround : using @MethodSource that is documented as :

an ArgumentsSource which provides access to values returned by methods of the class in which this annotation is declared.

This is designed to be used with @ParameterizedTest but it may fit to your case.

You could write :

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;    

public class FooTest {

  @ParameterizedTest
  @MethodSource("prepareTestJson")
  void add(JsonObject testJson_container) {
    // do your logic
  }

  private static Arguments prepareTestJson() {
     JsonObject testJson_container = new JsonObject();
     JsonObject testJson_inner = new JsonObject();
     String ContactInfo = "+1 111 111 1111";
     testJson_inner.addProperty("Contact", ContactInfo);
     testJson_container.add("ID", testJson_inner);
     return Arguments.of(testJson_container);
  }
} 

Upvotes: 3

Related Questions