我的控制器代码无法从MockMvc get请求中访问,我总是得到404



我试图模拟我的控制器并为它编写测试用例。但当我试图调试Test类时,控件没有进入我的controller类。我不确定我在这里做错了什么。

请帮我解决这个问题,因为我已经被困了将近3个多小时了。

我的服务等级


import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bnpp.leavemanagement.dao.DepartmentRepository;
import com.bnpp.leavemanagement.model.DepartmentModel;
@Service
public class DepartmentService 
{
@Autowired
DepartmentRepository depRepo;

public List<DepartmentModel> listDepartment = new ArrayList<>();

public List<DepartmentModel> getAllDepartments()
{
List<DepartmentModel> allDepartment = depRepo.findAll();
return allDepartment;
}

public DepartmentModel fetchDepartmentById( int id)
{
DepartmentModel depDetail = null;
try
{
depDetail = depRepo.findById(Long.valueOf(id)).get();
}
catch(Exception ex)
{
depDetail = null;
}
return depDetail;
}

public DepartmentModel addDepartment(DepartmentModel depDetail)
{
DepartmentModel depExists = null;
if (listDepartment.size() > 0) 
{
depExists = listDepartment.stream()
.filter(d -> d.getName().equalsIgnoreCase(depDetail.getName()))
.findFirst()
.orElse(null);
}

//Below condition is to restrict duplicate department creation
if(depExists == null)
{
depRepo.save(depDetail);
listDepartment.add(depDetail);
}
else
{
return null;
}

return depDetail;
}

public DepartmentModel updateDepartment(DepartmentModel depDetail)
{
DepartmentModel depUpdate = null;
try
{
depUpdate = depRepo.findById(depDetail.getId()).get();
depUpdate.setName(depDetail.getName());
depRepo.save(depUpdate);
} 
catch(Exception ex)
{
depUpdate = null;
}
return depUpdate;
}

public DepartmentModel deleteDepartment(DepartmentModel depDetail)
{
try
{
depRepo.deleteById(depDetail.getId());
}
catch(Exception ex)
{
return null;
}
return depDetail;
}

}

我的测试类


import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
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.context.annotation.Description;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.context.WebApplicationContext;
import com.bnpp.leavemanagement.controller.DepartmentController;
import com.bnpp.leavemanagement.model.DepartmentModel;
import com.bnpp.leavemanagement.service.DepartmentService;
@ExtendWith(MockitoExtension.class)
@WebMvcTest(DepartmentController.class)
@ContextConfiguration(classes = com.bnpp.leavemanagementsystem.LeaveManagementSystemApplicationTests.class)
public class DepartmentControllerTest {
@MockBean
DepartmentService depService;

@Autowired
private MockMvc mockMvc;

@InjectMocks
DepartmentController departmentController;

@Autowired
private WebApplicationContext webApplicationContext;

@Test
@Description("Should return a list of DepartmentModel objects when called")
void shouldReturnListOfDepartmentModel() throws Exception
{
DepartmentModel depModel = new DepartmentModel();
depModel.setId(1L);
depModel.setName("Mock");

List<DepartmentModel> listDepmodel = new ArrayList<>();
listDepmodel.add(depModel);

Mockito.when(depService.getAllDepartments()).thenReturn(listDepmodel);

mockMvc.perform(MockMvcRequestBuilders.get("/department"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.size()", Matchers.is(1)))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value("Mock"));
}
}

我的控制器类

package com.bnpp.leavemanagement.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.bnpp.leavemanagement.dao.DepartmentRepository;
import com.bnpp.leavemanagement.model.DepartmentModel;
import com.bnpp.leavemanagement.service.DepartmentService;
@RestController
public class DepartmentController 
{
@Autowired
DepartmentService depService;


@GetMapping("/department")
public ResponseEntity<List<DepartmentModel>> getDepartments()
{
List<DepartmentModel> allDepartment = depService.getAllDepartments();
if(allDepartment.size() == 0)
{
return new ResponseEntity( HttpStatus.NOT_FOUND);
}
return new ResponseEntity( allDepartment, HttpStatus.OK);
}

@GetMapping("/department/{id}")
public ResponseEntity<DepartmentModel> fetchDepartmentById(@PathVariable("id") int id)
{
DepartmentModel resDep = depService.fetchDepartmentById(id);
if(resDep == null)
{
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
else
{
return new ResponseEntity( resDep, HttpStatus.OK);
}
}

@PostMapping("/department/create")
public ResponseEntity<DepartmentModel> createDepartment(@RequestBody DepartmentModel depNew)
{
DepartmentModel resDep = depService.addDepartment(depNew);
if(resDep == null)
{
return new ResponseEntity(HttpStatus.EXPECTATION_FAILED);
}
else
{
return new ResponseEntity( resDep, HttpStatus.CREATED);
}
}

@PutMapping("/department/update")
public ResponseEntity<DepartmentModel> updateDepartment(@RequestBody DepartmentModel depNew)
{
DepartmentModel resDep = depService.updateDepartment(depNew);
if(resDep == null)
{
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
else
{
return new ResponseEntity( resDep, HttpStatus.OK);
}
}

@DeleteMapping("/department/delete")
public ResponseEntity<DepartmentModel> deleteDepartment(@RequestBody DepartmentModel depDel)
{
DepartmentModel resDep = depService.deleteDepartment(depDel);
if(resDep == null)
{
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
else
{
return new ResponseEntity(HttpStatus.OK);
}
}

}

使用MockMvc@WebMvcTest的最小可行测试设置如下:

@WebMvcTest(DepartmentController.class)
class DepartmentControllerTest {
@MockBean
DepartmentService depService;

@Autowired
private MockMvc mockMvc;
@Test
@Description("Should return a list of DepartmentModel objects when called")
void shouldReturnListOfDepartmentModel() throws Exception {
DepartmentModel depModel = new DepartmentModel();
depModel.setId(1L);
depModel.setName("Mock");

List<DepartmentModel> listDepmodel = new ArrayList<>();
listDepmodel.add(depModel);

Mockito.when(depService.getAllDepartments()).thenReturn(listDepmodel);

mockMvc.perform(MockMvcRequestBuilders.get("/department"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.size()", Matchers.is(1)))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value("Mock"));
}
}

说明:

  • @InjectMocks是不必要的,因为对于@MockBean,您正在将DepartmentService的模拟版本添加到Spring TestContext中,Spring DI的机制将其注入到DepartmentController

  • @ExtendWith(SpringExtension.class)也是冗余的,因为元注释@WebMvcTest已经激活了SpringExtension.class

  • 这里不需要@ContextConfiguration,因为@WebMvcTest会注意检测您的Spring Boot入口点类并启动切片上下文

如果测试仍然不起作用,请添加所有依赖项、代码的结构方式和主Spring Boot类(用@SpringBootApplication注释(。

进一步的阅读可能会揭示这一点:

  • @Mock和@MockBean之间的差异
  • 使用MockMvc测试Spring Boot应用程序指南

最新更新