How to autowire field in static @BeforeClass?

@RunWith(SpringJUnit4ClassRunner.class)
public void ITest {
    @Autowired
    private EntityRepository dao;

    @BeforeClass
    public static void init() {
        dao.save(initialEntity); //not possible as field is not static
    }
}

How can I have my service injected already in the static init class?


Solution 1:

With Junit 5 you can do this (@BeforeAll instead of @BeforeClass)

public void ITest {
    @Autowired
    private EntityRepository dao;

    @BeforeAll
    public static void init(@Autowired EntityRepository dao) {
        dao.save(initialEntity); //possible now as autowired function parameter is used
    }
}

By leaving the field it means it can be used in other tests

Solution 2:

One workaround that I have been using to get this working is to use @Before with a flag to skip it being executed for each testcase

@RunWith(SpringJUnit4ClassRunner.class)
public class BaseTest {

@Autowired
private Service1 service1;

@Autowired
private Service2 service2;

private static boolean dataLoaded = false;

@Before
public void setUp() throws Exception {

    if (!dataLoaded) {
        service1.something();
        service2.somethingElse();
        dataLoaded = true;
    }
  }
}

Solution 3:

It looks to me that you are trying to populate DB before tests.

I would give a try to two options:

  • If you can extract initial scripts to sql file (if that is option for you without using repository bean) you can use this approach and annotate your test with @Sql
  • You can explore DbUnit and here is link to spring dbunit connector which is doing exactly that and helping you populate DB before tests. Here is a github link for integrating between spring test framework and dbunit. After you do that you have @DatabaseSetup and @DatabaseTearDown which will do thing on DB you need

I know that this does not answer how to inject bean in static @BeforeClass but form code it looks it is solving your problem.

Update: I recently run into same problem in my project and dug out this article which helped me and I think it is elegant way of dealing with this type of problem. You can extend SpringJUnit4ClassRunner with listener which can do instance level setup with all your defined beans.