Spring Boot @ Перед вставленными данными нет данных - PullRequest
0 голосов
/ 26 сентября 2019

Я пишу простой тест аутентификации с JUnit4 и TestContainers.Оба моих метода @Before и @After являются @Transactional, но когда я запрашиваю данные в UserDetailsServiceImpl, их нет, и я не могу понять, почему.Там нет ничего асинхронного.Любые идеи.

@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<>());
    }
}

1 Ответ

1 голос
/ 27 сентября 2019

Это связано с тем, что в тестах транзакции по умолчанию откатываются.

В разделе документации, описывающей это поведение , также описывается, как изменить его при необходимости с помощью @Commitаннотация:

По умолчанию платформа создает и откатывает транзакцию для каждого теста.[...]

Если вы хотите зафиксировать транзакцию (необычно, но иногда полезно, когда вы хотите, чтобы конкретный тест заполнял или изменял базу данных), вы можете указать платформе TestContext вызвать транзакцию для фиксациивместо отката, используя аннотацию @Commit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...