使用模拟的测试错误:想要但未调用:
我尝试为我的弹簧启动控制器编写集成测试。这是我要测试的控制器方法:
@GetMapping("/")
public String getAllBooks(Model model, @RequestParam("page") Optional<Integer> page, @RequestParam("size") Optional<Integer> size) {
int currentPage = page.orElse(FIRST_PAGE);
int pageSize = size.orElse(DEFAULT_PAGE_SIZE);
Page<Book> bookPage = bookService.getAllBooks(PageRequest.of(currentPage - 1, pageSize));
Set<String> categories = bookService.findAllCategories();
model.addAttribute("categories", categories);
model.addAttribute("currentPage", currentPage);
model.addAttribute("books", bookPage);
int totalPages = bookPage.getTotalPages();
if (totalPages > 0) {
List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
.boxed()
.collect(Collectors.toList());
model.addAttribute("pageNumbers", pageNumbers);
}
return "library";
}
这是我的课程,带有测试:
@SpringBootTest
@AutoConfigureMockMvc
public class BookControllerTests {
@Autowired
private MockMvc mockMvc;
@Mock
BookService bookService;
@Mock
BookRepository bookRepository;
private final String category = "forTest";
final Book book = new Book("test1", 9999, "testAuthor1", 1, "test1");
@BeforeEach
public void initEach() {
bookService.addNewBook(book, category, "not used");
}
@AfterEach
public void deleteEach() {
bookRepository.deleteAll();
}
@Test
void getAllBooksTest() throws Exception {
mockMvc.perform(get("/")
.param("page", "1")
.param("size", "20"))
.andExpect(status().isOk());
ArgumentCaptor<Pageable> pageableCaptor = ArgumentCaptor.forClass(Pageable.class);
verify(bookRepository).findAll(pageableCaptor.capture());
PageRequest pageable = (PageRequest) pageableCaptor.getValue();
assertThat(pageable).hasPageNumber(1);
assertThat(pageable).hasPageSize(20);
}
}
我编写了自定义essertthat方法,它看起来像:
class PageableAssert extends AbstractAssert<PageableAssert, Pageable> {
PageableAssert(Pageable pageable) {
super(pageable, PageableAssert.class);
}
static PageableAssert assertThat(Pageable actual) {
return new PageableAssert(actual);
}
void hasPageSize(int expectedPageSize) {
if (!Objects.equals(actual.getPageSize(), expectedPageSize)) {
failWithMessage("expected page size to be <%s> but was <%s>", expectedPageSize, actual.getPageSize());
}
}
void hasPageNumber(int expectedPageNumber) {
if (!Objects.equals(actual.getPageNumber(), expectedPageNumber)) {
failWithMessage("expected page number to be <%s> but was <%s>", expectedPageNumber, actual.getPageNumber());
}
}
PageableAssert hasSort(String field, Sort.Direction direction) {
Sort.Order actualOrder = actual.getSort().getOrderFor(field);
if (actualOrder == null) {
failWithMessage("expected sort for field <%s> to be <%s> but was null", field, direction);
} else if (actualOrder.getDirection() != direction) {
failWithMessage("expected sort for field <%s> to be <%s> but was <%s>", field, direction, actualOrder.getDirection());
}
return this;
}
}
但是,正如我正确理解我的问题时,我出现在这一行中: 验证(bookrepository).findall(pageablecaptor.capture());
因此,我的自定义断言不会影响这种错误的发生,看起来像: 想要但不被调用: bookrepository.findall(); - &gt;在kpi.diploma.ovcharenko.controller.bookcontrollertests.getallbookstest(bookcontrollertests.java:58) 实际上,与此模拟的相互作用为零。 您能帮我解决这个问题吗,因为我完全不知道如何解决它。
I try to write integration tests for my Spring boot controller. Here is my controller method which I want to test:
@GetMapping("/")
public String getAllBooks(Model model, @RequestParam("page") Optional<Integer> page, @RequestParam("size") Optional<Integer> size) {
int currentPage = page.orElse(FIRST_PAGE);
int pageSize = size.orElse(DEFAULT_PAGE_SIZE);
Page<Book> bookPage = bookService.getAllBooks(PageRequest.of(currentPage - 1, pageSize));
Set<String> categories = bookService.findAllCategories();
model.addAttribute("categories", categories);
model.addAttribute("currentPage", currentPage);
model.addAttribute("books", bookPage);
int totalPages = bookPage.getTotalPages();
if (totalPages > 0) {
List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
.boxed()
.collect(Collectors.toList());
model.addAttribute("pageNumbers", pageNumbers);
}
return "library";
}
And here is my class with tests:
@SpringBootTest
@AutoConfigureMockMvc
public class BookControllerTests {
@Autowired
private MockMvc mockMvc;
@Mock
BookService bookService;
@Mock
BookRepository bookRepository;
private final String category = "forTest";
final Book book = new Book("test1", 9999, "testAuthor1", 1, "test1");
@BeforeEach
public void initEach() {
bookService.addNewBook(book, category, "not used");
}
@AfterEach
public void deleteEach() {
bookRepository.deleteAll();
}
@Test
void getAllBooksTest() throws Exception {
mockMvc.perform(get("/")
.param("page", "1")
.param("size", "20"))
.andExpect(status().isOk());
ArgumentCaptor<Pageable> pageableCaptor = ArgumentCaptor.forClass(Pageable.class);
verify(bookRepository).findAll(pageableCaptor.capture());
PageRequest pageable = (PageRequest) pageableCaptor.getValue();
assertThat(pageable).hasPageNumber(1);
assertThat(pageable).hasPageSize(20);
}
}
I wrote custom assertThat methods, which looks like:
class PageableAssert extends AbstractAssert<PageableAssert, Pageable> {
PageableAssert(Pageable pageable) {
super(pageable, PageableAssert.class);
}
static PageableAssert assertThat(Pageable actual) {
return new PageableAssert(actual);
}
void hasPageSize(int expectedPageSize) {
if (!Objects.equals(actual.getPageSize(), expectedPageSize)) {
failWithMessage("expected page size to be <%s> but was <%s>", expectedPageSize, actual.getPageSize());
}
}
void hasPageNumber(int expectedPageNumber) {
if (!Objects.equals(actual.getPageNumber(), expectedPageNumber)) {
failWithMessage("expected page number to be <%s> but was <%s>", expectedPageNumber, actual.getPageNumber());
}
}
PageableAssert hasSort(String field, Sort.Direction direction) {
Sort.Order actualOrder = actual.getSort().getOrderFor(field);
if (actualOrder == null) {
failWithMessage("expected sort for field <%s> to be <%s> but was null", field, direction);
} else if (actualOrder.getDirection() != direction) {
failWithMessage("expected sort for field <%s> to be <%s> but was <%s>", field, direction, actualOrder.getDirection());
}
return this;
}
}
But as I correctly understand my problem appears in this line:verify(bookRepository).findAll(pageableCaptor.capture());
so my custom asserts cannot influence the occurrence of this error which looks like:
Wanted but not invoked:
bookRepository.findAll();
-> at kpi.diploma.ovcharenko.controller.BookControllerTests.getAllBooksTest(BookControllerTests.java:58)
Actually, there were zero interactions with this mock.
Can you help me with this problem, because I totally don't know how I can fix it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的测试中,您正在验证
bookrepository.findall
被调用,但是在您正在测试的方法中,BookRepository甚至没有引用。您要验证的是
bookservice.getallbooks
和bookservice.findallcategories
正在调用。如果您想验证是否正确调用您的BookRepository Inconcations,请围绕BookService方法编写测试,因为我认为这是进行这些调用的地方。
另外,我应该补充一点,由于您正在测试的方法使用这些模拟的响应,因此您需要创建一个wher() - &gt; then()语句以确保这些调用返回一些数据,否则您将获得一个NULL指针异常到达此行时:
int totalpages = bookpage.getTotalPages();
类似,
In your test, you're verifying that
bookRepository.findAll
was invoked, but in the method you're testing, bookRepository isn't even referenced.What you want to verify is that
bookService.getAllBooks
andbookService.findAllCategories
are being invoked.If you want to verify that your bookRepository invocations are being called correctly, write a test around the bookService methods, as I assume this is where those calls are made.
Also, I should add that since your method under test uses a response from those mocks, you need to create a when()->then() statement to ensure that those calls return some data, otherwise you're going to get a null pointer exception when it reaches this line:
int totalPages = bookPage.getTotalPages();
Something like,