java - 空指针异常 JUnit Mockito
问题描述
我是 JUnit 和 Mockitio 的新手。当我运行下面的代码时,我得到 java.lang.NullPointerException: Cannot invoke "org.springframework.http.ResponseEntity.getStatusCodeValue()" 因为返回值 "com.learnit.testing.MyController.getUser(java.lang .Long)" 为空
@Controller
@RequestMapping("/api")
public class MyController {
@Autowired
private MyService service;
@GetMapping("/")
@ResponseBody
public ResponseEntity<Object> getUser(Long id) throws Exception {
return service.myResponse(id);
}
}
@Service
public class MyService {
@Autowired
private MyRepository repository;
public ResponseEntity<Object> myResponse(Long id) throws Exception{
MyData data=repository.findById(id).orElse(null);
if(data!=null)
return new ResponseEntity<>(HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
测试
@ExtendWith(MockitoExtension.class)
public class MyTest {
@InjectMocks
private MyController controller;
@Mock
private MyRepository repo;
@Mock
private MyService service;
@Test
public void checkService() throws Exception {
when(repo.findById((long)1)).thenReturn(null);
assertEquals(controller.getUser((long)1).getStatusCodeValue(), 500);
}
}
解决方案
There are several issues:
- You did not stub the behaviour of the
MyService#myResponse
method. You need to mock theMyService
instance as this is the direct dependency of theMyController
instance. Therefore, theMyRepository
don't needs to be mocked in this test case (unless you want to stub its methods for some reason, but I don't it in the current code). I would recommend you to replace the following:
when(repo.findById((long)1)).thenReturn(null);
with stubbing behaviour of the MyService
mock instance:
when(service.myResponse(1L)).thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
When you do this, the MyRepository test suite mock instance can be removed, as it is not required anymore.
- Check your imports, based on the usage of
@ExtendWith
annotation I assume you are using JUnit 5 here. Make sure that you actually use other classes fromorg.junit.jupiter.api
(for example@Test
andAssertions
). By default, the JUnit does not support backward compatibility with the JUnit 4. Still, I you want to keep the compatibility you should include thejunit-vintage-engine
artifact in your test runtime path.
P.S You need to think which class you actually want to test, that determines which instances should be mocked.
推荐阅读
- php - Woocommerce - 单击添加到购物车时同时添加插件产品和产品
- airflow - Airflow xcom 以列表格式返回一个字符串,而不仅仅是一个字符串值?
- sql - 带有间隔的日期的Oracle递归CTE
- spring-boot - NoClassDeffFoundError: org/springframework/data/jpa/repository/Repository
- django - models.E005 父模型 'xx' 中的字段 'xxx' 与父模型中的字段 'xxx' 冲突
- reactjs - 如何在 reactJS 中从 POST 请求 AJAXutil 中获取响应
- java - 如何在其他各种 ArrayLists 中迭代 ArrayList?
- excel - 返回基于两个标准排名的名称
- node.js - 使用 FieldPath 更新多个动态嵌套 Firestore 字段
- azure - 为什么我们在 Azure 门户中看不到服务总线主题的消息计数?