@MockBean не работает для @WebMvcTest с JUnit 5 и Sping Boot 2? - PullRequest
1 голос
/ 17 апреля 2019

Я исследовал подобные вопросы на StackOverflow и не могу найти основную причину в моем случае.

КОНТЕКСТ:

У меня есть @RestController в SpringBoot 2 с зависимостью от BookSearcherService. Я хочу издеваться над BookSearcherService, чтобы выполнить юнит-тест контроллера.

ОШИБКА:

org.springframework.web.util.NestedServletException: Запрос обработка не удалась; вложенным исключением является java.lang.NullPointerException в org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:1013) в org.springframework.web.servlet.FrameworkServlet.doGet (FrameworkServlet.java:897) в javax.servlet.http.HttpServlet.service (HttpServlet.java:634) в org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:882) в org.springframework.test.web.servlet.TestDispatcherServlet.service (TestDispatcherServlet.java:71) в javax.servlet.http.HttpServlet.service (HttpServlet.java:741) в org.springframework.mock.web.MockFilterChain $ ServletFilterProxy.doFilter (MockFilterChain.java:166) в org.springframework.mock.web.MockFilterChain.doFilter (MockFilterChain.java:133) в org.springframework.web.filter.RequestContextFilter.doFilterInternal (RequestContextFilter.java:99) в org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) в org.springframework.mock.web.MockFilterChain.doFilter (MockFilterChain.java:133) в org.springframework.web.filter.FormContentFilter.doFilterInternal (FormContentFilter.java:92) в org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) в org.springframework.mock.web.MockFilterChain.doFilter (MockFilterChain.java:133) в org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal (HiddenHttpMethodFilter.java:93) в org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) в org.springframework.mock.web.MockFilterChain.doFilter (MockFilterChain.java:133) в org.springframework.test.web.servlet.MockMvc.perform (MockMvc.java:182) в com.search.book.Booksearcher.controller.BookSearcherControllerMockMvcTest.canListAll (BookSearcherControllerMockMvcTest.java:54) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Method.invoke (Method.java:498) в org.junit.platform.commons.util.ReflectionUtils.invokeMethod (ReflectionUtils.java:532) в org.junit.jupiter.engine.execution.ExecutableInvoker.invoke (ExecutableInvoker.java:115) в org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda $ invokeTestMethod $ 6 (TestMethodTestDescriptor.java:171) в org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute (ThrowableCollector.java:72) в org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod (TestMethodTestDescriptor.java:167) в org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute (TestMethodTestDescriptor.java:114) в org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute (TestMethodTestDescriptor.java:59) в org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda $ executeRecursively $ 4 (NodeTestTask.java:108) в org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute (ThrowableCollector.java:72) в org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively (NodeTestTask.java:98) в org.junit.platform.engine.support.hierarchical.NodeTestTask.execute (NodeTestTask.java:74) в java.util.ArrayList.forEach (ArrayList.java:1257) вorg.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll (SameThreadHierarchicalTestExecutorService.java:38) в org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda $ executeRecursively $ 4 (NodeTestTask.java:112) в org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute (ThrowableCollector.java:72) в org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively (NodeTestTask.java:98) в org.junit.platform.engine.support.hierarchical.NodeTestTask.execute (NodeTestTask.java:74) в java.util.ArrayList.forEach (ArrayList.java:1257) в org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll (SameThreadHierarchicalTestExecutorService.java:38) в org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda $ executeRecursively $ 4 (NodeTestTask.java:112) в org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute (ThrowableCollector.java:72) в org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively (NodeTestTask.java:98) в org.junit.platform.engine.support.hierarchical.NodeTestTask.execute (NodeTestTask.java:74) в org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit (SameThreadHierarchicalTestExecutorService.java:32) в org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute (HierarchicalTestExecutor.java:57) в org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute (HierarchicalTestEngine.java:51) в org.junit.platform.launcher.core.DefaultLauncher.execute (DefaultLauncher.java:220) в org.junit.platform.launcher.core.DefaultLauncher.lambda $ выполнять $ 6 (DefaultLauncher.java:188) в org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams (DefaultLauncher.java:202) в org.junit.platform.launcher.core.DefaultLauncher.execute (DefaultLauncher.java:181) в org.junit.platform.launcher.core.DefaultLauncher.execute (DefaultLauncher.java:128) в org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run (JUnit5TestReference.java:89) в org.eclipse.jdt.internal.junit.runner.TestExecution.run (TestExecution.java:41) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:541) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:763) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java:463) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java:209) Вызывается: java.lang.NullPointerException at com.search.book.Booksearcher.controller.BookSearcherController.listAll (BookSearcherController.java:31) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Method.invoke (Method.java:498) в org.springframework.web.method.support.InvocableHandlerMethod.doInvoke (InvocableHandlerMethod.java:189) в org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest (InvocableHandlerMethod.java:138) в org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle (ServletInvocableHandlerMethod.java:102) в org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod (RequestMappingHandlerAdapter.java:892) в org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:797) в org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle (AbstractHandlerMethodAdapter.java:87) вorg.springframework.web.servlet.DispatcherServlet.doDispatch (DispatcherServlet.java:1038) в org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:942) в org.sprerweworkFrameworkServlet.java:1005) ... еще 59

КОД:

BookSearcherController.java:

@RestController
@RequestMapping("/book")
@RequiredArgsConstructor
public class BookSearcherController {

    private BookSearcherService bookSearcherService;

    @GetMapping(path = "/list", produces = { "application/json" })
    @ResponseBody
    public List<BookDto> listAll() {
        return bookSearcherService.listAll();
    }
}

BookSearcherService.java:

@Service
public class BookSearcherService {

    private BookSearcherCrudService bookSearcherCrudService;

    @Autowired
    void setBookSearcherRepository(BookSearcherCrudService bookSearcherCrudService) {
        this.bookSearcherCrudService = bookSearcherCrudService;
    }

    private BookSearcherRepository bookSearcherRepository;

    @Autowired
    void setBookSearcherRepository(BookSearcherRepository bookSearcherRepository) {
        this.bookSearcherRepository = bookSearcherRepository;
    }

    public List<BookDto> listAll() {
        List<Book> books = bookSearcherRepository.findAll();
        return books.stream()
                .map(bookSearcherCrudService::toDto)
                .collect(Collectors.toList());
    }
}

BookSearcherControllerMockMvcTest.java:

@WebMvcTest(controllers = BookSearcherController.class)
public class BookSearcherControllerMockMvcTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BookSearcherService bookSearcherService;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void canListAll() throws Exception {
        assertThat(bookSearcherService).isNotNull();
        assertThat(mockMvc).isNotNull();

        List<BookDto> books = asList(new BookDto("Title 1"), new BookDto("Title 2"), new BookDto("Title 3"));

        given(bookSearcherService.listAll()).willReturn(books);

        ResultActions perform = mockMvc.perform(get("/book/list"));
    }
}

POM.XML

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.search.book</groupId>
    <artifactId>book-searcher</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>book-searcher</name>
    <description>Project for books search</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-runner</artifactId>
            <scope>test</scope>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

ВОПРОС:

Проблема, как я уже говорил выше, заключается в том, что BookSearcherService при выполнении вызова на mockMvc имеет null.Это означает, что либо @MockBean не работает, либо я сделал ошибку, которую не могу обнаружить в течение нескольких часов.Я использую Java8.

1 Ответ

2 голосов
/ 23 апреля 2019

Проблема в том, что bookSearcherService не вводится в BookSearchController, потому что он использует @RequiredArgsConstructor, что в этом случае не создает правильный конструктор.

Документация @RequiredArgsConstructor гласит, что конструктор будет создан с параметрами для неинициализированных final или @NonNull полей. Однако bookSearcherService не является ни тем, ни другим, и поэтому он не добавляется в качестве параметра конструктора.

Таким образом, хотя макет сам по себе не равен нулю, он никогда не вводится в тестируемый контроллер.

...