【问题标题】:Null pointer exception in junit when trying to call findAll from the repository in Spring尝试从 Spring 中的存储库调用 findAll 时,junit 中的空指针异常
【发布时间】:2020-11-10 21:32:48
【问题描述】:

我开发了一个应用程序,它将与书籍相关的数据存储在 MongoDB 中,并使用 Spring Rest api 将数据传递到前端。在这里,我只从数据库中获取数据,因此只使用 GetMapping 并且工作正常。
当我尝试测试该 get 方法时,会出现空指针错误,并且在尝试 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);

【问题讨论】:

标签: java spring-boot unit-testing junit


【解决方案1】:

您需要为此在类级别提供注释,如下所示,如果您在要测试的变量上使用 spring boot 测试启动器 @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());
    }
    
    }

【讨论】:

  • 它不工作仍然提供空指针异常
  • 你能提供堆栈跟踪吗?
  • 错误是针对不同的测试用例,如果您看到您的测试用例有方法@Test public void getBooksTest(),但上面显示的空指针是针对另一个测试用例com.example.demo.BookControllerTest.testBooks(StudentControllerTest.java:55),请正确查看
  • 抱歉错误地提交了另一个项目的错误日志,更新为正确的。
【解决方案2】:

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

我想提出一些建议。

  • 在这种情况下,请使用@RunWith(MockitoJUnitRunner.class),因为没有使用加载完整的ApplicationContext,这会消耗大量时间。使用 MockitoJUnitRunner 很快,测试应该尽可能快。
  • 使用constructor injection 而不是field injection。阅读this。您的代码如下所示:
@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());
    }
}

参考资料:

【讨论】:

  • 如您所说已更改,但空指针异常仍然保持不变
猜你喜欢
  • 2014-05-31
  • 2018-01-02
  • 2018-08-27
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多