使用模拟的测试错误:想要但未调用:

发布于 2025-02-08 21:30:36 字数 3908 浏览 1 评论 0原文

我尝试为我的弹簧启动控制器编写集成测试。这是我要测试的控制器方法:

    @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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光病人 2025-02-15 21:30:36

在您的测试中,您正在验证bookrepository.findall被调用,但是在您正在测试的方法中,BookRepository甚至没有引用。

您要验证的是bookservice.getallbooksbookservice.findallcategories正在调用。

如果您想验证是否正确调用您的BookRepository Inconcations,请围绕BookService方法编写测试,因为我认为这是进行这些调用的地方。

另外,我应该补充一点,由于您正在测试的方法使用这些模拟的响应,因此您需要创建一个wher() - &gt; then()语句以确保这些调用返回一些数据,否则您将获得一个NULL指针异常到达此行时:int totalpages = bookpage.getTotalPages();

类似,

Page<Book> bookPage =  Mockito.mock(Page.class);
when(bookService.getAllBooks(any()).thenReturn(bookPage);

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 and bookService.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,

Page<Book> bookPage =  Mockito.mock(Page.class);
when(bookService.getAllBooks(any()).thenReturn(bookPage);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文