在试图从Spring中的存储库调用findAll时,junit中出现空指针异常



我开发了一个应用程序,它将与Books相关的数据存储在MongoDB中,并使用Spring Rest api将数据传递到前端。在这里,我只从数据库中获取数据,因此只使用GetMapping,它运行良好
当我尝试测试get方法时,会出现Null指针错误,并且在尝试findAll((数据时会发生这种错误。帮助我解决这个问题,并使该方法的测试工作良好。

API

@RestController
@RequestMapping("/api")
public class Controller {
@Autowired
BookRepository bookRepo;
@GetMapping("/books")
public List<Book> getBooks(){
return bookRepo.findAll();
}
}

单元测试类

class BookControllerTest {
private Controller controller;

@Mock
private BookRepository repository;
@Test
public void getBooksTest(){
Book b1 = new Book("12345","James","male");
Book b2 = new Book("67890","Vicky","Female");
List<Book> bookList = new ArrayList<>();
bookList.add(b1);
bookList.add(b2);
System.out.println(bookList);
when(repository.findAll()).thenReturn(bookList);
List<Book> newList = controller.getBooks();
System.out.println(newList);
assertEquals(2,newList.size());
}
}

错误日志

java.lang.NullPointerException
at com.example.demo.BookControllerTest.getBooksTest(BookControllerTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

51线为when(repository.findAll()).thenReturn(bookList);

您可以使用此处回答的@RunWith(SpringRunner.class)@RunWith(MockitoJUnitRunner.class)来进行测试。

我有几个建议。

  • 在这种情况下,使用@RunWith(MockitoJUnitRunner.class),因为不需要加载完整的ApplicationContext,这会消耗大量时间。使用MockitoJUnitRunner很快,测试应该尽可能快
  • 使用constructor injection而不是field injection。读一读。您的代码如下所示:
@RestController
@RequestMapping("/api")
public class BooksController {
private BookRepository bookRepository;
@Autowired
public BooksController(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
@GetMapping("/books")
public List<Books> getBooks() {
return bookRepository.findAll();
}
}
@RunWith(MockitoJUnitRunner.class)
public class BooksControllerTest {
@Mock
private BookRepository bookRepository;
private BooksController booksController;
@Before
public void setUp() {
booksController = new BooksController(bookRepository);
}
@Test
public void testBooksController() throws Exception {
Books b1 = new Books("b1");
Books b2 = new Books("b2");
List<Books> booksList = Arrays.asList(b1, b2);

when(bookRepository.findAll()).thenReturn(booksList);
List<Books> response = booksController.getBooks();
System.out.println(response);

assertEquals(2, response.size());
}
}

参考文献:

  • @RunWith(SpringRunner.class(vs@RunWith(MockitoJUnitRunner.class
  • http://olivergierke.de/2013/11/why-field-injection-is-evil/

您需要为此提供类级别的注释,如下所示,如果在要测试的变量上使用弹簧启动测试启动器@RunWith(SpringRunner.class)@RunWith(MockitoJUnitRunner.class)@InjectMocks

@RunWith(SpringRunner.class)
class BookControllerTest {
@InjectMocks
private Controller controller;

@Mock
private BookRepository repository;
@Test
public void getBooksTest(){
Book b1 = new Book("12345","James","male");
Book b2 = new Book("67890","Vicky","Female");
List<Book> bookList = new ArrayList<>();
bookList.add(b1);
bookList.add(b2);
System.out.println(bookList);
when(repository.findAll()).thenReturn(bookList);
List<Book> newList = controller.getBooks();
System.out.println(newList);
assertEquals(2,newList.size());
}

}

最新更新