我正在编写集成测试来测试我的端点,并且需要在构造之后立即在数据库中设置User,因此Spring Security Test注释@WithUserDetails
有一个用户从数据库中收集。
我的课程设置如下:
@RunWith(value = SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@WithUserDetails(value = "email@address.com")
public abstract class IntegrationTests {
@Autowired
private MockMvc mockMvc;
@Autowired
private Service aService;
@PostConstruct
private void postConstruct() throws UserCreationException {
// Setup and save user data to the db using autowired service "aService"
RestAssuredMockMvc.mockMvc(mockMvc);
}
@Test
public void testA() {
// Some test
}
@Test
public void testB() {
// Some test
}
@Test
public void testC() {
// Some test
}
}
然而,{strong>每个带注释的@PostConstruct
都会调用@Test
方法,即使我们没有再次实例化主类。
因为我们使用Spring Security Test(@WithUserDetails
),所以在我们可以使用JUnit注释@Before
之前,我们需要用户持久化到数据库。我们无法使用@BeforeClass
因为我们依赖@Autowired
服务:aService
。
我找到的解决方案是使用变量来确定我们是否已经设置了数据(见下文),但这感觉很脏并且会有更好的方法。
@PostConstruct
private void postConstruct() throws UserCreationException {
if (!setupData) {
// Setup and save user data to the db using autowired service "aService"
RestAssuredMockMvc.mockMvc(mockMvc);
setupData = true;
}
}
答案 0 :(得分:1)
TLDR:暂时保持原状。如果稍后在多个测试类中重复布尔标志,则创建自己的TestExecutionListener
。
在JUnit中,在执行的每个测试方法中调用测试类构造函数
因此,为每种测试方法调用@PostConstruct
是有道理的
根据JUnit和Spring的功能,你的解决方法也不错。特别是因为你在基础测试类中这样做了。
尽管不那么脏,但您可以使用@TestExecutionListeners
为您的测试类添加注释并提供自定义TestExecutionListener
,但在此处使用它时,它似乎有点过分。
在您没有/想要基类并且想要在多个类中添加布尔标志的上下文中,使用自定义TestExecutionListener
可能是有意义的。
这是一个例子。
自定义TestExecutionListener:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
public class MyMockUserTestExecutionListener extends AbstractTestExecutionListener{
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
MyService myService = testContext.getApplicationContext().getBean(MyService.class);
// ... do my init
}
}
测试课程已更新:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@WithUserDetails(value = "email@address.com")
@TestExecutionListeners(mergeMode = MergeMode.MERGE_WITH_DEFAULTS,
value=MyMockUserTestExecutionListener.class)
public abstract class IntegrationTests {
...
}
请注意,MergeMode.MERGE_WITH_DEFAULTS
对于将来自Spring Boot测试类的TestExecutionListener
与当前类的TestExecutionListener
中定义的@TestExecutionListeners
进行合并很重要。<登记/>
默认值为MergeMode.REPLACE_DEFAULTS
。