我正在尝试执行阅读方法的简单测试。我正在尝试使用反应性方法,因此为了测试整个上下文,我正在使用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());
});
}
}