我有模特
public class Student {
private String name;
// getter and setter
}
我已经实现了一个REST控制器,该控制器生成一个带有随机字符作为名称的学生对象。我有一个@RestController,绑定了一个为学生对象提供服务的@Service层,并再次生成了一个生成随机字符串的@Service层。我想通过模拟控制器和服务来使用JUnit测试我的应用程序。问题是我可以模拟为学生提供服务的控制器和服务,但未模拟stringGeneratorService服务层。
我的控制器
@RestController
public class StudentServer {
StudentService service;
@Autowired
public StudentServer(StudentService service) {
this.service = service;
}
@GetMapping("/generate-student")
public Student studentGenerator() {
return service.getRandomStudent();
}
}
服务学生对象的我的服务层
@Service("studentService")
public class StudentService {
StringGeneratorService stringService;
@Autowired
public StudentService(StringGeneratorService stringService) {
this.stringService = stringService;
}
public Student getRandomStudent() {
Student student = new Student();
student.setName(stringService.generateRandomAlphaString());
return student;
}
}
和我的RandomStringGenertor服务
@Service("stringGeneratorService")
public class StringGeneratorService {
Random random = new Random();
public String generateRandomAlphaNumericString() {
// returns a randomly generated string
}
}
我的JUnit测试类如下:
@RunWith(SpringRunner.class)
@WebMvcTest(StudentServer.class)
public class RestTest {
@Autowired
private MockMvc mockMvc;
@TestConfiguration
public static class TestConfig {
@Bean
public StudentService studentService(final StringGeneratorService stringGeneratorService){
return new StudentService(stringGeneratorService);
}
@Bean
public StringGeneratorService stringGeneratorService(){
return mock(StringGeneratorService.class);
}
}
@Autowired
private StudentService studentService;
@Autowired
public StringGeneratorService stringGeneratorService;
@Before
public void setUp() {
reset(stringGeneratorService);
}
@After
public void tearDown() {
verifyNoMoreInteractions(stringGeneratorService);
}
@Test
public void testGenerateStudent() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/generate-student"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(print())
.andExpect(MockMvcResultMatchers.jsonPath("$.name").isNotEmpty());
}
}
结果是正文= {“名称”:空}
有人可以知道我在做什么错吗?
在您的测试配置中,为StringGeneratorService
:return mock(StringGeneratorService.class);
定义了模拟,但是您没有定义方法的模拟行为。许多返回对象的方法的默认行为是返回null
,您会在结果中看到它。
您需要定义方法的模拟行为,如下所示:
@Bean
public StringGeneratorService stringGeneratorService() {
StringGeneratorService mock = mock(StringGeneratorService.class);
// adding the missing mocked method behavior here
when(mock.generateRandomAlphaNumericString()).thenReturn("expectedMockedValue");
return mock;
}
正如我所见,这是针对Rest Controller类的单元测试。
我建议按照以下惯例将测试班级命名为以下名称
类名称:StudentServer。class
Junit类名称:StudentServerTest。class
现在是您的真实问题。
1]我看到您已经自动关联了依赖类(StudentService。class。相反,您需要将其模拟为
@MockBean
private StudentService studentService;
2]您不需要在测试类中使用StringGeneratorService bean /对象,因为它的方法不会从您的控制器类中直接调用。
而是从您的服务类中调用其方法,并且由于您在模拟服务类本身,所以该类在您的控制器类中完全不可见。
删除此
@Autowired
public StringGeneratorService stringGeneratorService;
3]现在,如下定义模拟行为,然后断言
@Test
public void testGenerateStudent() throws Exception {
Student student = new Student();
student.setName("TestStudent");
Mockito.when(studentService.getRandomStudent()).thenReturn(student);
mockMvc.perform(MockMvcRequestBuilders.get("/generate-student"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(print())
.andExpect(MockMvcResultMatchers.jsonPath("$.name").isNotEmpty());
}