Java annotations - code simplifications

2019-01-28 17:59发布

I am looking for a way to simplify the following code.

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        // My configuration classes
})
public class MyServiceTest {
    @Autowired
    private MyService service;

    @Test
    public void myTest() {
        Assert.assertTrue(service != null);
    }
}

I have many configuration classes and I don't want to put them into each test class. So I got the idea to create my own annotation:

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        // My configuration classes
})
public @interface IntegrationTests {
}

I try to use it in the following way:

@IntegrationTests
public class MyServiceTest {
    @Autowired
    private MyService service;

    @Test
    public void myTest() {
        Assert.assertTrue(service != null);
    }
}

But it doesn't work. Any idea?

2条回答
Root(大扎)
2楼-- · 2019-01-28 18:16

The reason your custom composed annotation did not work is that JUnit does not support @RunWith as a meta-annotation. Thus, when you compose your annotation as follows...

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { /* configuration classes */ })
public @interface IntegrationTests {
}

... it is JUnit that cannot see that you want to use the SpringJUnit4ClassRunner.

Spring Framework 4.0 and greater should have no problem seeing the declarations of @WebAppConfiguration and @ContextConfiguration used as meta-annotations.

In other words, the following should work for you:

@WebAppConfiguration
@ContextConfiguration(classes = { /* configuration classes */ })
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IntegrationTests {
}

@RunWith(SpringJUnit4ClassRunner.class)
@IntegrationTests
public class MyServiceTest {
    @Autowired
    private MyService service;

    @Test
    public void myTest() {
        assertNotNull(service);
    }
}

As an alternative, you can use an abstract base test class as recommended by axtavt.

Regards,

Sam (author of the Spring TestContext Framework)

查看更多
贪生不怕死
3楼-- · 2019-01-28 18:33

You can place these annotation on a superclass:

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        // My configuration classes
})
public abstract class AbstractIntegrationTest { ... }

.

public class MyServiceTest extends AbstractIntegrationTest { ... }

This approach also allows you to declare common @Autowired dependencies in the base class and customize @ContextConfiguration classes in concrete tests.

查看更多
登录 后发表回答