java - Spring Boot @Before 插入数据不可用

标签 java spring-boot spring-data-jpa

我正在使用 JUnit4 和 TestContainers 编写一个简单的身份验证测试。我的 @Before@After 方法都是 @Transactional,但是当我查询 UserDetailsS​​erviceImpl 中的数据时,它不存在,我不明白为什么。没有什么异步的。任何想法。

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
@TestPropertySource(locations = "classpath:application-test.properties")
public abstract class DBEnabledTest {

  @Autowired
  protected EntityManager em;

  @ClassRule
  public static PostgreSQLContainer<?> sqlContainer = new PostgreSQLContainer<>("postgres:11")
      .withDatabaseName("test_scenarios")
      .withUsername("postgres")
      .withPassword("postgres");


  @BeforeClass
  public static void setupEnv() {    
    System.setProperty("spring.datasource.url", sqlContainer.getJdbcUrl());
    System.setProperty("spring.datasource.username", sqlContainer.getUsername());
    System.setProperty("spring.datasource.password", sqlContainer.getPassword());
    log.info("Running DB test with - " + sqlContainer.getJdbcUrl());
  }

  @After
  @Transactional
  public void truncateDb() {
      List<String> tables = em.createNativeQuery("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'").getResultList();
      for (String table : tables) {
          em.createNativeQuery("TRUNCATE TABLE " + table + " CASCADE").executeUpdate();
      }
  }

}
<小时/>
@AutoConfigureMockMvc
public class TestUserAuthentication extends DBEnabledTest {

  @Autowired
  private TestRestTemplate restTemplate;

  @Autowired
  private UserRepository userRepository;

  @Before
  @Transactional
  public void initDBForEachTestMethod() {
    User testUser = new User();
    testUser.setEmail("test@user.com");
    testUser.setPassword(new BCryptPasswordEncoder().encode("testUser1"));
    testUser.setFirstName("Jonh");
    testUser.setLastName("Dough");
    testUser.setRole(AppRole.USER);
    userRepository.saveAndFlush(testUser);  
  }

  @Test
  @Transactional
  public void test_authenticationSuccess() throws Exception {

    ResponseEntity<String> res =
        restTemplate.postForEntity(
            "/api/user/login", 
            JsonUtil.objectBuilder()
                    .put("email", "test@user.com")
                    .put("password", "testUser1")
                    .toString(),
                    String.class
        );

    assertTrue(res.getStatusCode().is2xxSuccessful());

    String body = res.getBody();

    JsonNode node = JsonUtil.nodeFromString(body);

    assertNotNull(node.get("id"));
    assertNotNull(node.get("token"));
    assertNotNull(node.get("refreshToken"));
    assertNotNull(node.get("expiresAt"));

    DecodedJWT decodedJWT = JWTUtil.verifyToken(node.get("token").asText(), jwtConfig.getSecret());

    assertEquals("test@user.com", decodedJWT.getSubject());
    assertEquals(AppRole.USER, AppRole.valueOf(decodedJWT.getClaim(JWTUtil.ROLE_CLAIM).asString()));
  }


}
<小时/>
@Component
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        com.concentric.scenarios.domain.user.User applicationUser = userRepository.findByEmail(email);
// data from @Before not available here !!!
        if (applicationUser == null || applicationUser.isDeleted()) {
            throw new UsernameNotFoundException(email);
        }
        if(applicationUser.getPassword() == null) {
            throw new IllegalAccessError();
        }
        return new org.springframework.security.core.userdetails.User(email, applicationUser.getPassword(), new ArrayList<>());
    }
}

最佳答案

这是因为在测试中事务默认会回滚。

section of the documentation describing this behaviour还描述了如何在需要时使用 @Commit 注释来更改它:

By default, the framework creates and rolls back a transaction for each test. [...]

If you want a transaction to commit (unusual, but occasionally useful when you want a particular test to populate or modify the database), you can tell the TestContext framework to cause the transaction to commit instead of roll back by using the @Commit annotation.

关于java - Spring Boot @Before 插入数据不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58120243/

相关文章:

java - 在 Android studio 中使用 Clipdrawable 时提高动画速度?

java - 编写android :button programmatically

java - 从 Java Map<String, Object> propertyMap 添加条目的*副本*

java - Spring boot启用注释被忽略

在 Chrome 中通过 Selenium webDriver 运行测试用例时出现 java.lang.NullPointerException

java - IntelliJ IDEA 使用 Lombok 编译错误

java - Spring Boot 服务器无法识别 HTTP header SOAPAction 的值

java - 如何在 Spring Boot JPA 项目中设置 JDBC 映射?

java - 实体更新导致错误: cascade ="all-delete-orphan" was no longer referenced by the owning entity

java - 在 Hibernate 中使用双向映射重复记录