0

I have a task where need to write alternative for TestNG @BeforeSuite using only Junit, where this extension will create test data and shared it to test class. After long research I found a good solution based on Junit API (BeforeAllCallback and ExtensionContext.Store.CloseableResource).

package org.example.firstPreconditionClassTest;

import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;

import lombok.*;
import org.example.StoreHelper;
import org.example.TestHelper;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

@RequiredArgsConstructor
public class BaseSetupExtension
        implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {

    private final TestHelper testHelper;
    private final StoreHelper storeHelper;
    private static int a, b;

    BaseSetupExtension(TestHelper testHelper) {
        this.testHelper = testHelper;
        this.storeHelper = new StoreHelper(testHelper);
    }

    @Override
    public void beforeAll(ExtensionContext context) {
        // We need to use a unique key here, across all usages of this particular extension.
        String uniqueKey = this.getClass().getName();
        Object value = context.getRoot().getStore(GLOBAL).get(uniqueKey);
        if (value == null) {
            // First test container invocation.
            context.getRoot().getStore(GLOBAL).put(uniqueKey, this);
            setup();
        }
    }

    // Callback that is invoked <em>exactly once</em>
    // before the start of <em>all</em> test containers.
    public void setup() {
        System.out.println("Before all test classes");
        storeHelper.printSomething();
        a = 111;
        b = 222;
        testHelper.firstMethod(a);
    }

    // Callback that is invoked <em>exactly once</em>
    // after the end of <em>all</em> test containers.
    // Inherited from {@code CloseableResource}
    public void close() throws Throwable {
        System.out.println("After all test classes");
    }

    public static int getA() {
        return a;
    }

    public static int getB() {
        return b;
    }
}

It is works for initialize data like int a, b. But if I try to add helper classes (testHelper - interface, StoreHelper - class) I catch error:

org.example.firstPreconditionClassTest.BaseSetupExtension.<init>()
java.lang.NoSuchMethodException: org.example.firstPreconditionClassTest.BaseSetupExtension.<init>()

Just creating empty constructor or any variant with constructor not fixed it. In test classes there helper initialize just with lombok annotation like @RequiredArgsConstructor and its works. I don't understand why it is don't work with precondition class.

P.S. In this case main requirement: test data should be created once before test / class / suite run and will be deleted only after run finished.

Thank you for your attention! Comments with code example will be very helpful.

Builder: Gradle Java: 17 Lombok: 1.18.22 Junit: 5.8.1

  • JUnit needs to create an instance first and this means it needs a no-args constructor. Who should make `TestHelper`, and how many instances of that class should be made? If the answer is 'just the one', just make a static final field. – rzwitserloot May 30 '23 at 12:12
  • @rzwitserloot I tried NoArg, but it is not work. if I correct understand your answer: I need TestHelper and StoreHelper in BaseSetupExtension for call methods from it (it is needed for object creation). Also it is precondition class that need to run once before any tests started, I just need one instance. Also for create StoreHelper instance I need put TestHelper to StoreHelper constructor. In test classes it is worked just with RequiredArgsConstructor – Instance054 May 30 '23 at 12:28
  • You __need__ a no-args constructor; the error this question asks is about not having one. I gather that once you add that no-args constructor, 'it does not work'. What does not work? I'm pretty sure that fixes one problem (you now have a no-args constructor) but creates another (whatever 'does not work' means). There's no way to do this without creating a no-args constructor, so focus instead on whatever 'does not work' means. – rzwitserloot May 30 '23 at 18:02

0 Answers0