java - java - 如何在java中为restful webservices运行简单的junit?
问题描述
我尝试为 2 种方法运行单元测试。当我JUnit
为方法运行测试时,testRetrieveAllHotels_ServiceLayer()
它成功运行,但是当我尝试JUnit
为方法运行测试时testRetrieveAllHotels_WebLayer()
,出现此错误:java.lang.NullPointerException
这是代码:
package com.xxx.restfultesting.controller;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Arrays;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import com.xxx.restfultesting.business.HotelBusinessService;
import com.xxx.restfultesting.model.Hotel;
@RunWith(SpringRunner.class)
@WebMvcTest(HotelController.class)
public class HotelControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private HotelBusinessService businessService;
@Test
public void testRetrieveAllHotels_ServiceLayer(){
businessService.retrieveAllHotels();
verify(businessService, times(1)).retrieveAllHotels();
}
@Test
public void testRetrieveAllHotels_WebLayer(){
HotelController hotelController = new HotelController();
when(businessService.retrieveAllHotels()).thenReturn(
Arrays.asList(new Hotel(1, "Sofitel", 120, 20),
new Hotel(2, "Ibis", 50, 40),
new Item(3, "Marriot", 200, 15)));
hotelController.retrieveAllHotels();
verify(businessService, times(1)).retrieveAllHotels();
}
酒店控制器:
package com.xxx.restfultesting.controller;
import java.net.URI;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import com.xxx.restfultesting.business.HotelBusinessService;
import com.xxx.restfultesting.model.Hotel;
@RestController
public class HotelController {
@Autowired
private HotelBusinessService businessService;
@GetMapping("/items")
public List<Hotel> retrieveAllHotels() {
System.out.println("Debugging 1");
List<Hotel> hotels = businessService.retrieveAllHotels();
return hotels;
}
酒店商务服务:
package com.xxx.restfultesting.business;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.restfultesting.data.HotelRepository;
import com.xxx.restfultesting.model.Hotel;
@Component
public class HotelBusinessService {
@Autowired
private HotelRepository repository;
public List<Hotel> retrieveAllHotels() {
System.out.println("Debugging 2");
List<Hotel> hotels = repository.findAll();
return hotels;
}
}
我将 System.out.println("Debugging 1") 放入 Controller 中的 retrieveAllHotels() 方法中,并将 System.out.println("Debugging 2") 放入 Service 中的 retrieveAllHotels() 方法中。这些仅用于调试。当我为 testRetrieveAllHotels_ServiceLayer() 方法运行 JUnit 测试时,它可以成功运行,但我没有在控制台中看到“Debugging 2”。
当我为 testRetrieveAllHotels_WebLayer() 方法运行 JUnit 测试时,我收到 java.lang.NullPointerException 错误,并在控制台中收到“Debugging 1”。我试图理解为什么在第一种情况下没有“调试 2”以及如何成功运行第二种方法。任何反馈将不胜感激!
解决方案
@WebMvcTest
- 我认为您正在尝试编写控制器测试,您已经在其中自动连接MockMvc
和模拟了服务类。
在testRetrieveAllHotels_ServiceLayer
测试中,您尝试调用模拟服务类中的方法并验证是否调用了该方法。由于您在测试本身中调用了模拟,因此测试将成功。
在testRetrieveAllHotels_WebLayer
测试中,您已经创建了自己的控制器实例并使用了模拟服务。要解决此问题,您必须Autowire
在测试中使用控制器或在类中使用基于构造函数的注入并将模拟传递给测试中的构造函数
这只会修复测试,但它不是测试控制器的正确方法。要解决的问题:
- 没有必要进行
testRetrieveAllHotels_ServiceLayer
测试。您可以删除此测试。 testRetrieveAllHotels_WebLayer
必须更新如下:public void testRetrieveAllHotels_WebLayer(){ when(businessService.retrieveAllHotels()).thenReturn( Arrays.asList(new Hotel(1, "Sofitel", 120, 20), new Hotel(2, "Ibis", 50, 40), new Item(3, "Marriot", 200, 15))); mockMvc.perform( get("/items")) .andExpect(status().isOk()); verify(businessService, times(1)).retrieveAllHotels(); }
推荐阅读
- sql - 您可以为另一列中的每个值制作一个序列吗
- reactjs - 是否可以用钩子记忆未知数量的组件?
- python - for循环将文件读入列表与列表中元素的顺序之间的差异
- firebase - 在 Firebase Auth 中更新电子邮件地址时发送验证电子邮件
- flutter - 当语言环境设置为“he”(希伯来语)时,Flutter CupertinoDatePicker 会向后显示时间(mm:hh 而不是 hh:mm)
- vue.js - Vue:从函数内部,如何等待另一个函数完成?
- python - 如何使用 pyvtk 将 3D 矢量场从 numpy 数组导出到 *.vtk 文件?
- azure - 具有一个字符串和一个字符串列表的相似性 API
- python - 删除后嵌套列表不更新
- android - 如何使用 ADB 和 UiAutomator 从模拟器中提取用户界面 XML