WebTestClient不发布对象

时间:2019-12-06 05:59:40

标签: unit-testing junit integration-testing spring-webflux

我正在尝试执行阅读方法的简单测试。我正在尝试使用反应性方法,因此为了测试整个上下文,我正在使用WebTestClient。尽管post方法似乎正常工作,但读取操作不起作用。但为什么?它不应该保存到嵌入式mongo数据库中吗? 如果这是反应性的,我需要以某种方式等待吗?

肯定会在服务中引发异常,因为我看到了

com.geborskimateusz.util.exceptions.NotFoundException:找不到productId为1的产品

这是测试的样子:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, properties = {"spring.data.mongodb.port: 0"})
public class MovieServiceApplicationTests {

    @Autowired
    WebTestClient webTestClient;

    @Autowired
    MovieService movieService;

    @Test
    public void getMovie() {
        Integer given = 1;

        postAndVerify(given, HttpStatus.OK);

        Movie movie = movieService.getMovie(given); **fails here**
        assertNotNull(movie);

        getAndVerify(given, HttpStatus.OK);

    }

    private WebTestClient.BodyContentSpec postAndVerify(Integer id, HttpStatus httpStatus) {
        Movie movie = Movie.builder()
                .movieId(id)
                .title("Title for movie " + id)
                .genre("Genre for movie " + id)
                .address("Address for movie " + id)
                .build();

        return webTestClient.post()
                .uri("/movie")
                .body(Mono.just(movie), Movie.class)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .exchange()
                .expectStatus().isEqualTo(httpStatus)
                .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
                .expectBody();
    }

    private WebTestClient.BodyContentSpec getAndVerify(Integer id, HttpStatus httpStatus) {
                return webTestClient.get()
                .uri("/movie/" + id)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .exchange()
                .expectStatus().isEqualTo(httpStatus)
                .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
                .expectBody()
                .jsonPath("$.movieId").isEqualTo(id)
                .jsonPath("$.genre").isNotEmpty()
                .jsonPath("$.title").isNotEmpty()
                .jsonPath("$.address").isNotEmpty();
    }
}

服务和存储库是非常简单的实现:

服务:

@Slf4j
@RestController
public class BaseMovieService implements MovieService {

    private final ServiceUtil serviceUtil;
    private final MovieRepository movieRepository;

    private final MovieMapper movieMapper = MovieMapper.INSTANCE;

    @Autowired
    public BaseMovieService(ServiceUtil serviceUtil, MovieRepository movieRepository) {
        this.serviceUtil = serviceUtil;
        this.movieRepository = movieRepository;
    }


    @Override
    public Movie getMovie(Integer movieId) {

        if (movieId < 1) throw new InvalidInputException("Invalid productId: " + movieId);

        MovieEntity movieEntity = movieRepository.findMovieById(movieId)
                .orElseThrow(() -> new NotFoundException("No product found for productId: " + movieId));

        Movie movie = movieMapper.entityToApi(movieEntity);
        movie.setAddress(serviceUtil.getServiceAddress());

        log.debug("/movie return the found movie for movieId={}", movieId);

        return movie;
    }

    @Override
    public Movie createMovie(Movie movie) {

        try {

            MovieEntity movieEntity = movieMapper.apiToEntity(movie);
            MovieEntity saved =  movieRepository.save(movieEntity);

            log.debug("createMovie: entity created for movieId: {}", movie.getMovieId());
            return movieMapper.entityToApi(saved);
        }catch (DuplicateKeyException e) {
            throw new InvalidInputException("Duplicate key for movieId: " +movie.getMovieId());
        }

    }

    @Override
    public void deleteMovie(Integer movieId) {

    }
}

然后回购:

public interface MovieRepository extends PagingAndSortingRepository<MovieEntity, String> {
    Optional<MovieEntity> findMovieById(Integer movieId);
}

但是这很奇怪,因为我确信仓库可以正常工作,下面的所有测试都通过了:

@ExtendWith(SpringExtension.class)
@DataMongoTest
public class MovieRepositoryTest {

    public static final int BASE_MOVIE_ID = 1;
    @Autowired
    MovieRepository movieRepository;

    MovieEntity savedMovieEntity;

    @BeforeEach
    void setUp() {
        movieRepository.deleteAll();

        MovieEntity movieEntity = MovieEntity
                .builder()
                .movieId(BASE_MOVIE_ID)
                .title("Raise of Jedi")
                .address("123.321.54x24")
                .genre("Sci-Fi")
                .build();

        savedMovieEntity = movieRepository.save(movieEntity);

        assertEqualsMovie(movieEntity, savedMovieEntity);
    }

    @Test
    void create() {
        MovieEntity movieEntity = MovieEntity
                .builder()
                .movieId(2)
                .title("Fall of Jedi")
                .address("125.721.54x24")
                .genre("Sci-Fi")
                .build();

        MovieEntity saved = movieRepository.save(movieEntity);

        assertEqualsMovie(movieEntity, saved);
        assertEquals(2, movieRepository.count());
    }

    @Test
    void update() {
        String givenTitle = "Updated Title";

        savedMovieEntity.setTitle(givenTitle);

        MovieEntity updated = movieRepository.save(savedMovieEntity);

        assertEquals(givenTitle, updated.getTitle());
    }

    @Test
    void findById() {
        Optional<MovieEntity> optionalMovieEntity = movieRepository.findById(savedMovieEntity.getId());

        assertTrue(optionalMovieEntity.isPresent());

        MovieEntity movieEntity = optionalMovieEntity.get();

        assertEqualsMovie(savedMovieEntity, movieEntity);
    }

    @Test
    void shouldPerformOptimisticLocking() {
        String concurrentM1actionData = "Concurrent action data performed on M1";
        String concurrentM2actionData = "Concurrent action data performed on M2";

        MovieEntity m1 = movieRepository.findById(savedMovieEntity.getId()).get();
        MovieEntity m2 = movieRepository.findById(savedMovieEntity.getId()).get();

        m1.setTitle(concurrentM1actionData);

        // by updating Entity its version should be updated
        movieRepository.save(m1);

        // should fail because of version mismatch
        try {
            m2.setTitle(concurrentM2actionData);
            movieRepository.save(m2);
            fail("Expected an OptimisticLockingFailureException");
        } catch (OptimisticLockingFailureException e) {
            System.out.println("shouldPerformOptimisticLocking() -> catch OptimisticLockingFailureException");
        }

        //check current version and state
        MovieEntity updatedMovieEntity = movieRepository.findById(savedMovieEntity.getId()).get();
        assertEquals(1, (int) updatedMovieEntity.getVersion());
        assertEquals(concurrentM1actionData, updatedMovieEntity.getTitle());
    }

    @Test
    void delete() {
        movieRepository.delete(savedMovieEntity);
        assertEquals(0, movieRepository.count());
    }

    @Test
    void duplicateMovieError() {
        MovieEntity duplicate = MovieEntity.builder().build();
        duplicate.setId(savedMovieEntity.getId());

        assertThrows(DuplicateKeyException.class, () -> movieRepository.save(duplicate));
    }

    @Test
    void paging() {

        bulkSaveMovie();

        Pageable nextPage = PageRequest.of(0, 4, Sort.Direction.ASC, "movieId");

        nextPage = verifyPages(nextPage, "[1, 2, 3, 4]", true);
        nextPage = verifyPages(nextPage, "[5, 6, 7, 8]", true);
        verifyPages(nextPage, "[9, 10]", false);

    }

    private Pageable verifyPages(Pageable nextPage, String idsAsString, boolean hasNext) {
        Page<MovieEntity> moviePage = movieRepository.findAll(nextPage);
        assertEquals(hasNext, moviePage.hasNext());

        String ids = moviePage.get().map(MovieEntity::getMovieId).collect(Collectors.toList()).toString();
        assertEquals(idsAsString, ids);
        return nextPage.next();
    }

    private void bulkSaveMovie() {
        movieRepository.deleteAll();

        List<MovieEntity> movies = IntStream.rangeClosed(1, 10)
                .mapToObj(i -> MovieEntity.builder()
                        .movieId(i)
                        .title("Movie nr: " + i)
                        .build())
                .collect(Collectors.toList());

        movieRepository.saveAll(movies);
    }


    private void assertEqualsMovie(MovieEntity expected, MovieEntity actual) {
        assertAll("Executing assertEqualsMovie(..)", () -> {
            assertEquals(expected.getId(), actual.getId());
            assertEquals(expected.getVersion(), actual.getVersion());
            assertEquals(expected.getMovieId(), actual.getMovieId());
            assertEquals(expected.getTitle(), actual.getTitle());
            assertEquals(expected.getAddress(), actual.getAddress());
            assertEquals(expected.getGenre(), actual.getGenre());
        });
    }
}

0 个答案:

没有答案