当我指定我的类型的 Optional 时,为什么 Mockito return null
Why does Mockito return null when I specify an Optional of my type
我在控制器上有一个方法可以获取聊天室所有惩罚类型的列表(踢、禁止、警告和静音)。在第一次测试中,当我模拟数据时,它按预期工作并且测试通过。
然而,在我的第二次测试中,我提供了。我将应该 returned 的内容定义为 Optional<Punishment>
,并将 punishmentName 的属性设置为“静音”。我很困惑为什么这会给我 null
。当我在测试之外 运行 Spring 应用程序时,路由工作正常。出于某种原因,模拟从不想 return 我指定的值,但只是空值。具体来说,这是在 .andExpect(jsonPath("$.punishmentName", Matchers.equalTo("mute")));
行的测试中发现的,因为字段值为 null 并给出以下错误:
java.lang.AssertionError: No value at JSON path "$.punishmentName"
为清楚起见,我还提供了控制器方法和服务方法。
惩罚控制器测试:
@WebMvcTest(PunishmentController.class)
@RunWith(SpringRunner.class)
public class PunishmentControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private PunishmentService punishmentService;
@MockBean
private PunishmentValidator punishmentValidator;
@Test
public void getAllPunishmentTypesReturnsAListOfPunishmentTypes() throws Exception {
List<Punishment> punishments = new ArrayList<>();
punishments.add(new Punishment("mute"));
punishments.add(new Punishment("kick"));
punishments.add(new Punishment("ban"));
punishments.add(new Punishment("warn"));
Mockito.when(punishmentService.getAllPunishmentTypes()).thenReturn(punishments);
mvc.perform(get("/api/punishments"))
.andExpect(status().isOk())
.andExpect(jsonPath("$", Matchers.hasSize(4)))
.andExpect(jsonPath("$[0].punishmentName", Matchers.equalTo("mute")))
.andExpect(jsonPath("$[1].punishmentName", Matchers.equalTo("kick")))
.andExpect(jsonPath("$[2].punishmentName", Matchers.equalTo("ban")))
.andExpect(jsonPath("$[3].punishmentName", Matchers.equalTo("warn")));
}
@Test
public void getPunishmentTypeReturnsMuteWhenMuteIsSpecified() throws Exception {
Optional<Punishment> mute = Optional.of(new Punishment("mute"));
Mockito.when(punishmentService.getPunishmentType("mute")).thenReturn(mute);
mvc.perform(get("/api/punishments/mute"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.punishmentName", Matchers.equalTo("mute")));
}
控制器方法:
/**
* GET request for all punishment types.
* @return List<Punishment> - When Punishments are found in the database they are returned in a List object.
* Otherwise, an empty list is returned if no records are found or an error occurs.
*/
@GetMapping
public List<Punishment> getAllPunishments() {
return punishmentService.getAllPunishmentTypes();
}
/**
* GET request for one punishment type.
* @param punishmentType String - The type of punishment.
* @return Optional<Punishment> - The rule that gets returned or an empty optional if no rule is found.
*/
@GetMapping(path = "{punishmentType}")
public Optional<Punishment> getPunishment(@PathVariable("punishmentType") String punishmentType) {
boolean isPunishmentTypeValid = punishmentValidator.validatePunishmentName(punishmentType);
if (isPunishmentTypeValid) {
return punishmentService.getPunishmentType(punishmentType);
} else {
return Optional.empty();
}
}
}
服务方式:
/**
* Gets all the punishment types
* @return List<Punishment> - The rules in the community
*/
public List<Punishment> getAllPunishmentTypes() {
return punishmentRepository.findAll();
}
/**
* Gets a specific punishment type.
* @param punishmentType String - The type of punishment.
* @return The punishment retrieved.
*/
public Optional<Punishment> getPunishmentType(String punishmentType) {
return punishmentRepository.findById(punishmentType);
}
我相信这是因为你忘记模拟方法 PunishmentValidator#validatePunishmentName("mute")
到 return true
这样你在 PunishmentService
上存根的方法永远不会被调用,因为默认情况下,如果您不存根方法,它将 return false(参见 this)。
另外它是一个 known behaviour that @MockBean
is configured as lenient stubbing 如果你存根一个方法但它实际上没有被执行,它不会报告错误(即抛出 UnnecessaryStubbingException
)。
所以更改以下内容应该可以解决您的问题:
@Test
public void getPunishmentTypeReturnsMuteWhenMuteIsSpecified() throws Exception {
Optional<Punishment> mute = Optional.of(new Punishment("mute"));
Mockito.when(punishmentService.getPunishmentType("mute")).thenReturn(mute);
Mockito.when(punishmentValidator.validatePunishmentName("mute")).thenReturn(true);
mvc.perform(get("/api/punishments/mute"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.punishmentName", Matchers.equalTo("mute")));
}
我在控制器上有一个方法可以获取聊天室所有惩罚类型的列表(踢、禁止、警告和静音)。在第一次测试中,当我模拟数据时,它按预期工作并且测试通过。
然而,在我的第二次测试中,我提供了。我将应该 returned 的内容定义为 Optional<Punishment>
,并将 punishmentName 的属性设置为“静音”。我很困惑为什么这会给我 null
。当我在测试之外 运行 Spring 应用程序时,路由工作正常。出于某种原因,模拟从不想 return 我指定的值,但只是空值。具体来说,这是在 .andExpect(jsonPath("$.punishmentName", Matchers.equalTo("mute")));
行的测试中发现的,因为字段值为 null 并给出以下错误:
java.lang.AssertionError: No value at JSON path "$.punishmentName"
为清楚起见,我还提供了控制器方法和服务方法。
惩罚控制器测试:
@WebMvcTest(PunishmentController.class)
@RunWith(SpringRunner.class)
public class PunishmentControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private PunishmentService punishmentService;
@MockBean
private PunishmentValidator punishmentValidator;
@Test
public void getAllPunishmentTypesReturnsAListOfPunishmentTypes() throws Exception {
List<Punishment> punishments = new ArrayList<>();
punishments.add(new Punishment("mute"));
punishments.add(new Punishment("kick"));
punishments.add(new Punishment("ban"));
punishments.add(new Punishment("warn"));
Mockito.when(punishmentService.getAllPunishmentTypes()).thenReturn(punishments);
mvc.perform(get("/api/punishments"))
.andExpect(status().isOk())
.andExpect(jsonPath("$", Matchers.hasSize(4)))
.andExpect(jsonPath("$[0].punishmentName", Matchers.equalTo("mute")))
.andExpect(jsonPath("$[1].punishmentName", Matchers.equalTo("kick")))
.andExpect(jsonPath("$[2].punishmentName", Matchers.equalTo("ban")))
.andExpect(jsonPath("$[3].punishmentName", Matchers.equalTo("warn")));
}
@Test
public void getPunishmentTypeReturnsMuteWhenMuteIsSpecified() throws Exception {
Optional<Punishment> mute = Optional.of(new Punishment("mute"));
Mockito.when(punishmentService.getPunishmentType("mute")).thenReturn(mute);
mvc.perform(get("/api/punishments/mute"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.punishmentName", Matchers.equalTo("mute")));
}
控制器方法:
/**
* GET request for all punishment types.
* @return List<Punishment> - When Punishments are found in the database they are returned in a List object.
* Otherwise, an empty list is returned if no records are found or an error occurs.
*/
@GetMapping
public List<Punishment> getAllPunishments() {
return punishmentService.getAllPunishmentTypes();
}
/**
* GET request for one punishment type.
* @param punishmentType String - The type of punishment.
* @return Optional<Punishment> - The rule that gets returned or an empty optional if no rule is found.
*/
@GetMapping(path = "{punishmentType}")
public Optional<Punishment> getPunishment(@PathVariable("punishmentType") String punishmentType) {
boolean isPunishmentTypeValid = punishmentValidator.validatePunishmentName(punishmentType);
if (isPunishmentTypeValid) {
return punishmentService.getPunishmentType(punishmentType);
} else {
return Optional.empty();
}
}
}
服务方式:
/**
* Gets all the punishment types
* @return List<Punishment> - The rules in the community
*/
public List<Punishment> getAllPunishmentTypes() {
return punishmentRepository.findAll();
}
/**
* Gets a specific punishment type.
* @param punishmentType String - The type of punishment.
* @return The punishment retrieved.
*/
public Optional<Punishment> getPunishmentType(String punishmentType) {
return punishmentRepository.findById(punishmentType);
}
我相信这是因为你忘记模拟方法 PunishmentValidator#validatePunishmentName("mute")
到 return true
这样你在 PunishmentService
上存根的方法永远不会被调用,因为默认情况下,如果您不存根方法,它将 return false(参见 this)。
另外它是一个 known behaviour that @MockBean
is configured as lenient stubbing 如果你存根一个方法但它实际上没有被执行,它不会报告错误(即抛出 UnnecessaryStubbingException
)。
所以更改以下内容应该可以解决您的问题:
@Test
public void getPunishmentTypeReturnsMuteWhenMuteIsSpecified() throws Exception {
Optional<Punishment> mute = Optional.of(new Punishment("mute"));
Mockito.when(punishmentService.getPunishmentType("mute")).thenReturn(mute);
Mockito.when(punishmentValidator.validatePunishmentName("mute")).thenReturn(true);
mvc.perform(get("/api/punishments/mute"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.punishmentName", Matchers.equalTo("mute")));
}