6

I have a test case which has an @Autowired field. I would like to have one method for setting up the test case, as it has many @Test-annotated methods that will rely on the same generated data, (for which I need the autowired class).

What's a good way to achieve this?

If I have the @BeforeClass, then I need to make the method static, which breaks the autowiring.

carlspring
  • 31,231
  • 29
  • 115
  • 197

3 Answers3

4

1st solution

Use TestNG instead.
@Before* annotations behave this way in TestNG.
No method annotated with @Before* has to be static.

@org.testng.annotations.BeforeClass
public void setUpOnce() {
   //I'm not static!
}

2nd solution

And if you don't want to do that, you can use an execution listener from Spring (AbstractTestExecutionListener).

You will have to annotate your test class like this:

@TestExecutionListeners({CustomTestExecutionListener.class})
public class Test {
    //Some methods with @Test annotation.
}

And then implement CustomTestExecutionListener with this method:

public void beforeTestClass(TestContext testContext) throws Exception {
    //Your before goes here.
}

Self-contained in one file that would look like:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"commonContext.xml" })
@TestExecutionListeners({SimpleTest.class})
public class SimpleTest extends AbstractTestExecutionListener {

    @Override
    public void beforeTestClass(TestContext testContext) {
        System.out.println("In beforeTestClass.");
    }

    @Test
    public void test() {
        System.out.println("In test.");
    }
}
Community
  • 1
  • 1
Grzegorz Górkiewicz
  • 4,496
  • 4
  • 22
  • 38
  • This looks great, but my whole project has `JUnit` tests and I wasn't hoping to throw them away. – carlspring Feb 18 '17 at 19:57
  • 1
    @carlspring, that is why I have added something else from Spring to my answer (no need to use TestNG, if you opt for the second solution) ;) – Grzegorz Górkiewicz Feb 18 '17 at 19:59
  • Can the test class itself be the listener? – carlspring Feb 18 '17 at 20:41
  • So far used it as top-level class in another file. If it does not work, I would extend `AbstractTestExecutionListener` in an inner class... in the same `Test.java` file. – Grzegorz Górkiewicz Feb 18 '17 at 20:49
  • Grzegorz, it looks like your solution could do the trick, but I can't get it to work. Would you mind adding a really simple working example? I have this: https://gist.github.com/carlspring/662d8033fece212c3cd5718ed333142c and it's never hitting the `beforeTestClass` method. What am I doing wrong? – carlspring Feb 18 '17 at 23:07
  • 1
    Added a working example. No need to create yet another inner class (my bad). The `SimpleTest` class is enough ;) – Grzegorz Górkiewicz Feb 19 '17 at 00:01
  • I've almost gotten it to work, but the `@Autowired` class doesn't seem to be getting injected by Spring (which was my initial problem). – carlspring Feb 19 '17 at 12:40
  • 1
    Will have another look at this in the evening, cause I'm on mobile now. – Grzegorz Górkiewicz Feb 19 '17 at 12:43
  • For the second solution, why can't I access the `@Autowired` spring stereo-typed services on the methods of `AbstractTestExecutionListener `. In addition to that, why can't I use any global variables on the class initialised on the same interface? – David B Oct 13 '17 at 10:04
3

I came up with the solution of creating a separate initialization method (not setUp) annotated with @PostConstruct. This is not really an elegant solution, but it makes sure that the autowired/injected fields are properly initialized by Spring before using them, (which was the initial problem with the statically @BeforeClass annotated method).

carlspring
  • 31,231
  • 29
  • 115
  • 197
0

Using Junit 5 you are allowed to use an @Autowired annotation in the static @BeforeAll context like this:

public class TestClass {

    @Autowired
    private ApplicationContext context;

    @BeforeAll
    public static void beforeAll(@Autowired ApplicationContext context) {
        context.doSomething() //possible now as autowired function parameter is used
    }
}
Benjamin
  • 3,217
  • 2
  • 27
  • 42