java 为什么我使用mockito和模型Map器的服务单元测试没有失败?

nkhmeac6  于 2023-06-20  发布在  Java
关注(0)|答案(1)|浏览(85)

我对Spring和Mockito很陌生,我被困在一个教程中。我有一个简单的服务,这是从仓库取书

@Service
public class BookService {

    private  BookRepository bookRepository;
    private  ModelMapper modelMapper;

    public BookService(BookRepository bookRepository, ModelMapper modelMapper) {
        this.bookRepository = bookRepository;
        this.modelMapper = modelMapper;
    }

    public List<BookDto> fetchAllBooks() {
        List<Book> books = bookRepository.findAll();
        return books.stream()
            .map(convertBookModelToBookDto())
            .collect(Collectors.toList());
    }

    private Function<Book, BookDto> convertBookModelToBookDto() {
        return book -> modelMapper.map(book, BookDto.class);
    }
}

然后,我有一个简单的单元测试的服务,只有一个测试

@ExtendWith(MockitoExtension.class)
public class BookServiceTest {

@InjectMocks
private BookService bookService;

@Mock
private BookRepository bookRepository;

@Mock
private ModelMapper mapper;

private List<Book> books;
private List<BookDto> bookDtos;

@BeforeEach
public void setUp() {
    Book book = getBook("Lord of the Rings", "J.R.R. Tolkien", 1951, "Trilogy");
    Book book2 = getBook("Dune", "Frank Herbert", 1960, "Part I");
    Book book3 = getBook("Hobbit", "J.R.R. Tolkien", 1947, "Story");
    books = new ArrayList<>();
    books.add(book);
    books.add(book2);
    books.add(book3);
    
    BookDto bookDto = getBookDto("Lord of the Rings", "J.R.R. Tolkien", 1951, "Trilogy");
    BookDto bookDto2 = getBookDto("Dune", "Frank Herbert", 1960, "Part I");
    BookDto bookDto3 = getBookDto("Hobbit", "J.R.R. Tolkien", 1947, "Story");
    bookDtos = new ArrayList<>();
    bookDtos.add(bookDto);
    bookDtos.add(bookDto2);
    bookDtos.add(bookDto3);
    
    MockitoAnnotations.openMocks(this);
}

/**
 * Test of fetchAllBooks method, of class BookService.
 */
@Test
public void testFetchAllBooks() {
    Book book = books.get(0);
    // Mockito.doReturn(bookDtos.get(2)).when(mapper).map(book, BookDto.class);
    // Mockito.doReturn(books).when(bookRepository).findAll();
    Mockito.when(bookRepository.findAll()).thenReturn(books);
    Mockito.when(mapper.map(book, BookDto.class))
        .thenReturn(bookDtos.get(0), bookDtos.get(1), bookDtos.get(2));
    List<BookDto> fetchedBooks = bookService.fetchAllBooks();
    assertThat(fetchedBooks.size()).isEqualTo(3);
    assertThat(fetchedBooks.get(0))
        .hasFieldOrPropertyWithValue("title", "Lord of the Rings")
        .hasFieldOrPropertyWithValue("author", "J.R.R. Tolkien")
        .hasFieldOrPropertyWithValue("releaseYear", 1951)
        .hasFieldOrPropertyWithValue("description", "Trilogy");
    assertThat(fetchedBooks.get(1))
        .hasFieldOrPropertyWithValue("title", "Dune")
        .hasFieldOrPropertyWithValue("author", "Frank Herbert")
        .hasFieldOrPropertyWithValue("releaseYear", 1960)
        .hasFieldOrPropertyWithValue("description", "Part I");
    assertThat(fetchedBooks.get(2))
        .hasFieldOrPropertyWithValue("title", "Hobbit")
        .hasFieldOrPropertyWithValue("author", "J.R.R. Tolkien")
        .hasFieldOrPropertyWithValue("releaseYear", 1947)
        .hasFieldOrPropertyWithValue("description", "Story");
}

private Book getBook(String title, String author, int year, String description) {
    return Book.builder()
            .author(author)
            .title(title)
            .releaseYear(year)
            .description(description)
            .build();
}

private BookDto getBookDto(String title, String author, int year, String description) {
    return BookDto.builder()
            .author(author)
            .title(title)
            .releaseYear(year)
            .description(description)
            .build();
}
}

这是我对模型Map器的配置

@Configuration
public class ModelMapperConfiguration {

@Bean
public ModelMapper modelMapper() {
    return new ModelMapper();
}
}

这是我的Book实体类

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "books")
public class Book implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(columnDefinition = "NUMERIC(19,0)")
private Long id;

@Column(name = "title", nullable = false, unique = true)
private String title;

@Column(name = "description", nullable = false)
private String description;

@Column(name = "author", nullable = false)
private String author;

@Column(name = "release_year", nullable = false)
private Integer releaseYear;
}

这是我的BookDto课

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BookDto {

private Long id;

private String title;

private String description;

private String author;

private Integer releaseYear;
}

我不知道为什么我的单元测试没有失败,因为它应该是因为这一行

Mockito.doReturn(bookDtos.get(2)).when(mapper).map(book, BookDto.class);

因为它应该为每个所获取的书返回第三本书dto,所以关于第一和第二所获取的书的Assert应该失败…
我不知道我在这里错过了什么。
Sping Boot 2.7.12 Mockito 5.3.1 Assertj 3.24.2 Model Mapper 3.1.1 JUnit 5 Java 17

编辑1

在Assert的书籍取得我使用的书籍,而不是fetchedBooks。
但现在运行测试时出现以下错误:

java.lang.AssertionError: Expecting actual not to be null

在这一行:

.hasFieldOrPropertyWithValue("title", "Dune")
vc6uscn9

vc6uscn91#

谢谢你的评论,事实上问题是我对mockito的误解。
下面是修复后的测试,它现在可以按照我的预期工作。

@Test
public void testFetchAllBooks() {
    Mockito.doReturn(bookDtos.get(0))
            .when(mapper).map(books.get(0), BookDto.class);
    Mockito.doReturn(bookDtos.get(1))
            .when(mapper).map(books.get(1), BookDto.class);
    Mockito.doReturn(bookDtos.get(2))
            .when(mapper).map(books.get(2), BookDto.class);
    Mockito.doReturn(books)
            .when(bookRepository).findAll();
    List<BookDto> fetchedBooks = bookService.fetchAllBooks();
    assertThat(fetchedBooks.size()).isEqualTo(3);
    assertThat(fetchedBooks.get(0))
        .hasFieldOrPropertyWithValue("title", "Lord of the Rings")
        .hasFieldOrPropertyWithValue("author", "J.R.R. Tolkien")
        .hasFieldOrPropertyWithValue("releaseYear", 1951)
        .hasFieldOrPropertyWithValue("description", "Trilogy");
    assertThat(fetchedBooks.get(1))
        .hasFieldOrPropertyWithValue("title", "Dune")
        .hasFieldOrPropertyWithValue("author", "Frank Herbert")
        .hasFieldOrPropertyWithValue("releaseYear", 1960)
        .hasFieldOrPropertyWithValue("description", "Part I");
    assertThat(fetchedBooks.get(2))
        .hasFieldOrPropertyWithValue("title", "Hobbit")
        .hasFieldOrPropertyWithValue("author", "J.R.R. Tolkien")
        .hasFieldOrPropertyWithValue("releaseYear", 1947)
        .hasFieldOrPropertyWithValue("description", "Story");
}

相关问题