【发布时间】:2018-01-23 16:15:03
【问题描述】:
这可能是一个愚蠢的问题或显而易见的问题,但是,我真的很难解决这个问题。 假设我们在被测方法中有以下逻辑:
@Service
public class ServiceToTest() {
@Autowired
private SomeService someService;
public String testMethod() {
Map<String, String> parameters = new HashMap<String, String>();
// eventParameters will be populated inside someService
String result = someService.doLogic(parameters);
// do something with the result here that doesn't really matter for this example
String name = parameters.get("name").toLowerCase();
return name;
}
}
在SomeService 内部,参数映射填充了一些值,例如本例中的“名称”。我想在我的单元测试中模拟这个服务。
考虑以下单元测试sn-p:
@RunWith(SpringRunner.class)
public class ServiceToTestTest {
@TestConfiguration
static class ServiceToTestConfiguration {
@Bean
public ServiceToTest serviceToTest() {
return new ServiceToTest();
}
@Autowired
private ServiceToTest serviceToTest;
@MockBean
private SomeService someService;
@Test
public void testShouldReturnJimmy() {
given(someService.doLogic(Mockito.anyMap())).willReturn("whatever");
String name = serviceToTest.testMethod();
assertThat(name).isEqualTo("jimmy");
}
}
当我执行这个测试时,我在这一行得到一个 NullPointerException:
String name = parameters.get("name").toLowerCase();,这是有道理的,因为应该填充此映射的方法被模拟并且 parameters.get("name") 为空。我们还假设我真的想要从doLogic(parameters) 返回一个字符串,所以它不能是参数映射。
有没有办法以某种方式指示模拟对象填充参数映射,或模拟映射对象本身?
(这里的代码示例是为这篇文章即时编写的,所以如果我在编写它们时没有注意到任何愚蠢的错误,请原谅我;-))
【问题讨论】:
-
有办法的。但这表明代码应该被重构。为什么不从 doLogic() 返回一个包含结果字符串的对象和一个 Map?
-
是的,这是一个选项,但恕我直言,这对我来说似乎有点违反直觉。创建另一个对象来存储我想从我的方法返回的对象和我只想丰富的 Map... 我想重构的最佳方法是在 SomeService 中创建一个专用的公共方法来丰富/填充地图并返回它。这样我就可以轻松地模拟我想要在地图中返回的内容。我刚做了这个,效果很好:)
-
感谢 JB 为我指明重构的方向!
标签: java spring-boot junit mockito