[Unit Testing Java] Unit testing with Mockito vs. integration testing
作者:互联网
Service:
package com.example.ec.service; import com.example.ec.domain.Tour; import com.example.ec.domain.TourRating; import com.example.ec.repo.TourRatingRepository; import com.example.ec.repo.TourRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import javax.transaction.Transactional; import java.util.*; /** * Tour Rating Service * * Created by Mary Ellen Bowman. */ @Service @Transactional public class TourRatingService { private TourRatingRepository tourRatingRepository; private TourRepository tourRepository; /** * Construct TourRatingService * * @param tourRatingRepository Tour Rating Repository * @param tourRepository Tour Repository */ @Autowired public TourRatingService(TourRatingRepository tourRatingRepository, TourRepository tourRepository) { this.tourRatingRepository = tourRatingRepository; this.tourRepository = tourRepository; } /** * Create a new Tour Rating in the database * * @param tourId tour identifier * @param customerId customer identifier * @param score score of the tour rating * @param comment additional comment * @throws NoSuchElementException if no Tour found. */ public void createNew(int tourId, Integer customerId, Integer score, String comment) throws NoSuchElementException { tourRatingRepository.save(new TourRating(verifyTour(tourId), customerId, score, comment)); } /** * Get All Ratings. * * @return List of TourRatings */ public List<TourRating> lookupAll() { return tourRatingRepository.findAll(); } public Optional<TourRating> lookupRatingById(int id) { return tourRatingRepository.findById(id); } /** * Get a page of tour ratings for a tour. * * @param tourId tour identifier * @param pageable page parameters to determine which elements to fetch * @return Page of TourRatings * @throws NoSuchElementException if no Tour found. */ public Page<TourRating> lookupRatings(int tourId, Pageable pageable) throws NoSuchElementException { return tourRatingRepository.findByTourId(verifyTour(tourId).getId(), pageable); } /** * Update some of the elements of a Tour Rating. * * @param tourId tour identifier * @param score score of the tour rating * @param comment additional comment * @return Tour Rating Domain Object * @throws NoSuchElementException if no Tour found. */ public TourRating update(int tourId, Integer customerId, Integer score, String comment) throws NoSuchElementException { TourRating rating = verifyTourRating(tourId, customerId); rating.setScore(score); rating.setComment(comment); return tourRatingRepository.save(rating); } /** * Update all of the elements of a Tour Rating. * * @param tourId tour identifier * @param customerId customer identifier * @param score score of the tour rating * @param comment additional comment * @return Tour Rating Domain Object * @throws NoSuchElementException if no Tour found. */ public TourRating updateSome(int tourId, Integer customerId, Integer score, String comment) throws NoSuchElementException { TourRating rating = verifyTourRating(tourId, customerId); if (score != null) { rating.setScore(score); } if (comment!= null) { rating.setComment(comment); } return tourRatingRepository.save(rating); } /** * Delete a Tour Rating. * * @param tourId tour identifier * @param customerId customer identifier * @throws NoSuchElementException if no Tour found. */ public void delete(int tourId, Integer customerId) throws NoSuchElementException { TourRating rating = verifyTourRating(tourId, customerId); tourRatingRepository.delete(rating); } /** * Get the average score of a tour. * * @param tourId tour identifier * @return average score as a Double. * @throws NoSuchElementException */ public Double getAverageScore(int tourId) throws NoSuchElementException { List<TourRating> ratings = tourRatingRepository.findByTourId(verifyTour(tourId).getId()); OptionalDouble average = ratings.stream().mapToInt((rating) -> rating.getScore()).average(); return average.isPresent() ? average.getAsDouble():null; } /** * Service for many customers to give the same score for a service * @param tourId * @param score * @param customers */ public void rateMany(int tourId, int score, Integer [] customers) { Tour tour = tourRepository.findById(tourId).orElseThrow(() -> new NoSuchElementException("rateMany, no valid tourId")); for (Integer c : customers) { tourRatingRepository.save(new TourRating(tour, c, score)); } } /** * Verify and return the Tour given a tourId. * * @param tourId * @return the found Tour * @throws NoSuchElementException if no Tour found. */ private Tour verifyTour(int tourId) throws NoSuchElementException { return tourRepository.findById(tourId).orElseThrow(() -> new NoSuchElementException("Tour does not exist " + tourId) ); } /** * Verify and return the TourRating for a particular tourId and Customer * @param tourId * @param customerId * @return the found TourRating * @throws NoSuchElementException if no TourRating found */ private TourRating verifyTourRating(int tourId, int customerId) throws NoSuchElementException { return tourRatingRepository.findByTourIdAndCustomerId(tourId, customerId).orElseThrow(() -> new NoSuchElementException("Tour-Rating pair for request(" + tourId + " for customer" + customerId)); } }
Unit testing:
package com.example.ec.service; import com.example.ec.domain.Tour; import com.example.ec.domain.TourRating; import com.example.ec.repo.TourRatingRepository; import com.example.ec.repo.TourRepository; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.Arrays; import java.util.Optional; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class TourRatingServiceTest { private static final int CUSTOMER_ID = 123; private static final int TOUR_ID = 1; private static final int TOUR_RATING_ID = 100; @Mock private TourRepository tourRepositoryMock; @Mock TourRatingRepository tourRatingRepositoryMock; // will inject tourRepositoryMock, tourRatingRepositoryMock to service @InjectMocks private TourRatingService service; @Mock private Tour tourMock; @Mock private TourRating tourRatingMock; /** * Mock Response to commonly invoked methods */ @Before public void setupReturnValuesOfMockMethods() { when(tourRepositoryMock.findById(TOUR_ID)).thenReturn(Optional.of(tourMock)); when(tourMock.getId()).thenReturn(TOUR_ID); when(tourRatingRepositoryMock.findByTourIdAndCustomerId(TOUR_ID,CUSTOMER_ID)).thenReturn(Optional.of(tourRatingMock)); when(tourRatingRepositoryMock.findByTourId(TOUR_ID)).thenReturn(Arrays.asList(tourRatingMock)); } @Test public void lookupRatingById() { when(tourRatingRepositoryMock.findById(TOUR_RATING_ID)).thenReturn(Optional.of(tourRatingMock)); //invoke and verify lookupRatingById assertThat(service.lookupRatingById(TOUR_RATING_ID).get(), is(tourRatingMock)); } @Test public void lookupAll() { when(tourRatingRepositoryMock.findAll()).thenReturn(Arrays.asList(tourRatingMock)); //invoke and verify lookupAll assertThat(service.lookupAll().get(0), is(tourRatingMock)); } @Test public void getAverageScore() { when(tourRatingMock.getScore()).thenReturn(10); //invoke and verify getAverageScore assertThat(service.getAverageScore(TOUR_ID), is(10.0)); } @Test public void lookupRatings() { //create mocks of Pageable and Page (only needed in this test) Pageable pageable = mock(Pageable.class); Page page = mock(Page.class); when(tourRatingRepositoryMock.findByTourId(1, pageable)).thenReturn(page); //invoke and verify lookupRatings assertThat(service.lookupRatings(TOUR_ID, pageable), is(page)); } /************************************************************************************** * * Verify the invocation of dependencies. * **************************************************************************************/ @Test public void delete() { //invoke delete service.delete(1,CUSTOMER_ID); //verify tourRatingRepository.delete invoked verify(tourRatingRepositoryMock).delete(any(TourRating.class)); } @Test public void rateMany() { //invoke rateMany service.rateMany(TOUR_ID, 10, new Integer[]{CUSTOMER_ID, CUSTOMER_ID + 1}); //verify tourRatingRepository.save invoked twice verify(tourRatingRepositoryMock, times(2)).save(any(TourRating.class)); } @Test public void update() { //invoke update service.update(TOUR_ID,CUSTOMER_ID,5, "great"); //verify tourRatingRepository.save invoked once verify(tourRatingRepositoryMock).save(any(TourRating.class)); //verify and tourRating setter methods invoked verify(tourRatingMock).setComment("great"); verify(tourRatingMock).setScore(5); } @Test public void updateSome() { //invoke updateSome service.updateSome(TOUR_ID, CUSTOMER_ID, 1, "awful"); //verify tourRatingRepository.save invoked once verify(tourRatingRepositoryMock).save(any(TourRating.class)); //verify and tourRating setter methods invoked verify(tourRatingMock).setComment("awful"); verify(tourRatingMock).setScore(1); } /************************************************************************************** * * Verify the invocation of dependencies * Capture parameter values. * Verify the parameters. * **************************************************************************************/ @Test public void createNew() { //prepare to capture a TourRating Object ArgumentCaptor<TourRating> tourRatingCaptor = ArgumentCaptor.forClass(TourRating.class); //invoke createNew service.createNew(TOUR_ID, CUSTOMER_ID, 2, "ok"); //verify tourRatingRepository.save invoked once and capture the TourRating Object verify(tourRatingRepositoryMock).save(tourRatingCaptor.capture()); //verify the attributes of the Tour Rating Object assertThat(tourRatingCaptor.getValue().getTour(), is(tourMock)); assertThat(tourRatingCaptor.getValue().getCustomerId(), is(CUSTOMER_ID)); assertThat(tourRatingCaptor.getValue().getScore(), is(2)); assertThat(tourRatingCaptor.getValue().getComment(), is("ok")); } }
Integration testing:
package com.example.ec.service; import com.example.ec.domain.TourRating; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.NoSuchElementException; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** * Created by Mary Ellen Bowman */ @RunWith(SpringRunner.class) @SpringBootTest @Transactional public class TourRatingServiceIntegrationTest { private static final int CUSTOMER_ID = 456; private static final int TOUR_ID = 1; private static final int NOT_A_TOUR_ID = 123; @Autowired private TourRatingService service; //Happy Path delete existing TourRating. @Test public void delete() { List<TourRating> tourRatings = service.lookupAll(); service.delete(tourRatings.get(0).getTour().getId(), tourRatings.get(0).getCustomerId()); assertThat(service.lookupAll().size(), is(tourRatings.size() - 1)); } //UnHappy Path, Tour NOT_A_TOUR_ID does not exist @Test(expected = NoSuchElementException.class) public void deleteException() { service.delete(NOT_A_TOUR_ID, 1234); } //Happy Path to Create a new Tour Rating @Test public void createNew() { //would throw NoSuchElementException if TourRating for TOUR_ID by CUSTOMER_ID already exists service.createNew(TOUR_ID, CUSTOMER_ID, 2, "it was fair"); //Verify New Tour Rating created. TourRating newTourRating = service.verifyTourRating(TOUR_ID, CUSTOMER_ID); assertThat(newTourRating.getTour().getId(), is(TOUR_ID)); assertThat(newTourRating.getCustomerId(), is(CUSTOMER_ID)); assertThat(newTourRating.getScore(), is(2)); assertThat(newTourRating.getComment(), is ("it was fair")); } //UnHappy Path, Tour NOT_A_TOUR_ID does not exist @Test(expected = NoSuchElementException.class) public void createNewException() { service.createNew(NOT_A_TOUR_ID, CUSTOMER_ID, 2, "it was fair"); } //Happy Path many customers Rate one tour @Test public void rateMany() { int ratings = service.lookupAll().size(); service.rateMany(TOUR_ID, 5, new Integer[]{100, 101, 102}); assertThat(service.lookupAll().size(), is(ratings + 3)); } //Unhappy Path, 2nd Invocation would create duplicates in the database, DataIntegrityViolationException thrown @Test(expected = DataIntegrityViolationException.class) public void rateManyProveRollback() { int ratings = service.lookupAll().size(); Integer customers[] = {100, 101, 102}; service.rateMany(TOUR_ID, 3, customers); service.rateMany(TOUR_ID, 3, customers); } //Happy Path, Update a Tour Rating already in the database @Test public void update() { createNew(); TourRating tourRating = service.update(TOUR_ID, CUSTOMER_ID, 1, "one"); assertThat(tourRating.getTour().getId(), is(TOUR_ID)); assertThat(tourRating.getCustomerId(), is(CUSTOMER_ID)); assertThat(tourRating.getScore(), is(1)); assertThat(tourRating.getComment(), is("one")); } //Unhappy path, no Tour Rating exists for tourId=1 and customer=1 @Test(expected = NoSuchElementException.class) public void updateException() throws Exception { service.update(1, 1, 1, "one"); } //Happy Path, Update a Tour Rating already in the database @Test public void updateSome() { createNew(); TourRating tourRating = service.update(TOUR_ID, CUSTOMER_ID, 1, "one"); assertThat(tourRating.getTour().getId(), is(TOUR_ID)); assertThat(tourRating.getCustomerId(), is(CUSTOMER_ID)); assertThat(tourRating.getScore(), is(1)); assertThat(tourRating.getComment(), is("one")); } //Unhappy path, no Tour Rating exists for tourId=1 and customer=1 @Test(expected = NoSuchElementException.class) public void updateSomeException() throws Exception { service.update(1, 1, 1, "one"); } //Happy Path get average score of a Tour. @Test public void getAverageScore() { assertTrue(service.getAverageScore(TOUR_ID) == 4.0); } //UnHappy Path, Tour NOT_A_TOUR_ID does not exist @Test(expected = NoSuchElementException.class) public void getAverageScoreException() { service.getAverageScore(NOT_A_TOUR_ID); //That tour does not exist } }
标签:Mockito,service,testing,public,Tour,tourId,import,ID,Unit 来源: https://www.cnblogs.com/Answer1215/p/14176526.html