了解SpringBootTest中的TestExecutionListeners和BaseTest类

时间:2019-05-14 07:56:14

标签: spring-boot tdd spring-test

我正在尝试进行一些测试。 我的疑问是要针对当前运行的Test的父类TestExecutionListener@Before的执行顺序执行@After的Order。

示例:

我有一个类,可以在测试配置文件的表中设置一些虚拟用户并将其删除。因此,我为用户相关项目创建了一个基类。 我的基类如下:

public abstract class BaseDataTest {
    @Autowired
    private UserRepository userRepository;

    private TestUserGenerator testUserGenerator;

    @Before
    public void setUp() {
        testUserGenerator = new TestUserGenerator(userRepository);
        testUserGenerator.createTestUsers();
    }

    @After
    public void cleanUp() {
        testUserGenerator.deleteTestUsers();
        testUserGenerator = null;
    }
}

我现在有两种情况:

  1. 只需插入用户,然后再从数据库中获取更多信息,并且用户存在于测试数据库中即可。
  2. 我必须插入测试用户,以后再检查特定用户,然后从当前登录用户的blocked表中提取所有用户。

对于方案1,它工作正常,因为Test类上没有TestExecutionListener批注,因此可以正确调用基类方法setUp / cleanUp,并且我的测试运行良好。我的测试课程如下:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class UserInsertTest extends BaseDataTest {

    @Autowired
    UserRepository userRepository;


    @Test
    public void testThatSystemHasUsers() {
        Assert.assertNotSame(userRepository.count(), 0);
    }

}

对于不起作用的情况2,因为我拥有TestExecutionListener类,并且具有WithSecurityContextTestExecutionListener类作为值,因为没有调用我的setUp方法,并且系统没有用户证明认证测试失败。 我的BlockUserTest类如下:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
@TestExecutionListeners(value = {WithSecurityContextTestExecutionListener.class})
public class BlockUserTest extends BaseDataTest {

    @Autowired
    private AppUserDetailsService userDetailsService;

    @Autowired
    private BlockService blockRepository;

    @Test
    @WithUserDetails(value = "sabrinahuff@comstruct.com")
    public void blockNoneReturnEmpty() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = userDetailsService.loadUserByUsername(authentication.getName());
        List<Block> blockedByMe = blockRepository.getBlockedByMe(user.getId(), PageRequest.of(0, Integer.MAX_VALUE));

        Assert.assertNotNull(blockedByMe);
        //as i have not blocked anyone yet in test    
        Assert.assertSame(blockedByMe.size(), 0);
    }

}

我得到了

    java.lang.IllegalStateException: Unable to create SecurityContext using @org.springframework.security.test.context.support.WithUserDetails(value=sabrinahuff@comstruct.com, userDetailsServiceBeanName=, setupBefore=TEST_METHOD)

    at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:126)
    at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:96)
    at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.beforeTestMethod(WithSecurityContextTestExecutionListener.java:62)
    at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:291)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NullPointerException
    at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:63)
    at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:44)
    at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:123)
    ... 24 more


java.lang.NullPointerException
    at com.pkg.BaseDataTest.cleanUp(BaseDataTest.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

2019-05-14 13:21:23.104  INFO 17612 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2019-05-14 13:21:23.108  INFO 17612 --- [       Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2019-05-14 13:21:23.109  INFO 17612 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2019-05-14 13:21:23.112  INFO 17612 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

由于内部principal为null,这似乎是有效的,因为db中没有测试用户,因此以空值返回loadUserByUsername。

org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory中的方法

public SecurityContext createSecurityContext(WithUserDetails withUser) {
        String beanName = withUser.userDetailsServiceBeanName();
        UserDetailsService userDetailsService = this.findUserDetailsService(beanName);
        String username = withUser.value();
        Assert.hasLength(username, "value() must be non empty String");
        UserDetails principal = userDetailsService.loadUserByUsername(username);
        Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        context.setAuthentication(authentication);
        return context;
    }

保持TestExecutionListener和测试数据生成,我如何才能通过块用户测试。谢谢!

Spring SecurityTest

@Test
    @WithUserDetails(value = "brysonhensley@yahoo.com")
    public void test() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Assert.assertEquals(1, 1);
    }

这似乎可行,并且在调试后,我的身份验证对象中填充了有意义的值,因此我认为是UserDetailsService bean名称。

0 个答案:

没有答案