#java #maven #unit-testing #spring-boot #junit5
#java #maven #модульное тестирование #весенняя загрузка #junit5
Вопрос:
Я исследовал похожие вопросы в 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.Дофильтруйте (MockFilterChain.java:133) в org.springframework.web.filter.RequestContextFilter .doFilterInternal(RequestContextFilter.java:99) в org.springframework.web.filter.OncePerRequestFilter.Дофильтруйте (OncePerRequestFilter.java:107) в org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133) в org.springframework.web.filter.FormContentFilter.Внутренний фильтр (FormContentFilter.java:92) в org.springframework.web.filter.OncePerRequestFilter.Дофильтруйте (OncePerRequestFilter.java:107) в org.springframework.mock.web.MockFilterChain.Дофильтруйте (MockFilterChain.java:133) в org.springframework.web.filter.Скрытый HttpMethod фильтр.doFilterInternal(hiddenhttpmethod Filter.java:93) в org.springframework.web.filter.OncePerRequestFilter.Дофильтруйте (OncePerRequestFilter.java:107) в org.springframework.mock.web.MockFilterChain.Дофильтруйте (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. поразмышляйте.Делегирование methodaccessorimpl.invoke(делегирование methodaccessorimpl.java:43) в java.lang.reflect.Метод.invoke(метод.java: 498) в организации.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532) в org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115) в org.junit.jupiter.engine.дескриптор.TestMethodTestDescriptor.лямбда-метод $ invokeTestMethod $ 6(TestMethod testdescriptor.java:171) в org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72) в org.junit.jupiter.engine.дескриптор.TestMethod testdescriptor.invokeTestMethod(TestMethod testdescriptor.java:167) в org.junit.jupiter.engine.дескриптор.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114) в org.junit.jupiter.engine.дескриптор.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.executerэкурсивно (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.Выбрасываемый Collector.execute(выбрасываемый collector.java:72) в org.junit.platform.engine.support.hierarchical.NodeTestTask.executerэкурсивно (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 .отправить(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.лямбда $выполнить $ 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 в com.search.book.Booksearcher.controller.BookSearcherController.listAll(BookSearcherController.java:31) в sun.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) в sun.reflect.Делегирование methodaccessorimpl.invoke(делегирование methodaccessorimpl.java:43) в java.lang.reflect.Метод.invoke(метод.java:498) в org.springframework.web.method.support.Метод InvocableHandlerMethod.Выполните вызов (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.springframework.web.servlet.FrameworkServlet.ProcessRequest(FrameworkServlet.java:1005) … еще 59
CODE:
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
has null
. Это означает, что либо @MockBean
не работает, либо я допустил ошибку, которую не удается обнаружить в течение нескольких часов. Я использую Java8
.
Комментарии:
1. Проблема, вероятно, в том, что
bookSearcherService
он не вводится,BookSearchController
потому что он использует@RequiredArgsConstructor
which не добавляет@Autowired
аннотацию.2. @ArhoHuttunen Это помогло.
3. Хорошо, тогда я сделаю это ответом.
Ответ №1:
Проблема в том, что bookSearcherService
он не вводится, BookSearchController
потому что он использует @RequiredArgsConstructor
, который в этом случае не создает правильный конструктор.
В @RequiredArgsConstructor
документации указано, что будет создан конструктор с параметрами для неинициализированных final
@NonNull
полей or . Однако это ни то, bookSearcherService
ни другое, и поэтому оно не добавляется в качестве параметра конструктора.
Таким образом, хотя сам макет не равен нулю, он никогда не вводится в тестируемый контроллер.
Комментарии:
1. Я был уверен, что
@RequiredArgsConstructor
это делает работу@Autowired
. Спасибо.2. Он должен работать как отдельный конструктор, который будет использоваться начиная с spring 4.2 или 4.3 iirc, немного странная проблема
3. На самом деле вы правы, но
@RequiredArgsConstructor
правильно ли работает здесь, посколькуbookSearcherService
ниfinal
то, ни@NonNull
другое?4. Я изменил ответ, чтобы отразить это.