所有,感谢帮助。我对Mockito还是很陌生,如果我有一个Service类,一个控制器类(通过传递Map参数使用该服务),我该如何模拟该服务方法?Helloworldservice.java package service; import java.util.Map; public class Helloworldservice { public String greeting() { return "Hello, World"; } public String greetingSB(Map<String, String> sb) { return "Hello," + sb.get("name"); } }Helloworldcontroller.java package controller; import java.util.HashMap; import java.util.Map; import service.Helloworldservice; public class Helloworldcontroller { private Helloworldservice hservice; public Helloworldcontroller() { // TODO Auto-generated constructor stub hservice = new Helloworldservice(); } public String sayHello() { return hservice.greeting(); } public String sayHelloSB() { Map<String, String> sb = new HashMap<String, String>(); sb.put("name", "somebody"); return hservice.greetingSB(sb); } }HelloworldcontrollerTest.java package unit.controller; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import controller.Helloworldcontroller; import service.Helloworldservice; @RunWith(MockitoJUnitRunner.class) public class HelloworldcontrollerTest { @InjectMocks private Helloworldcontroller hcontroller; private Helloworldservice hservice = new Helloworldservice(); @Mock private Helloworldservice hservice_mock; @Before public void setup() { hservice_mock = Mockito.spy(hservice); /** I am not sure how to mock here for that param sb Mockito.when(hservice_mock.greetingSB(.......)) .thenReturn("Hello, somebody"); **/ } @Test public void testGreeting() { String h = hcontroller.sayHelloSB(); Assert.assertEquals(h, "Hello, sombody!!!"); } }服务总是返回null,我不确定是什么错误。 最佳答案 您的示例代码有点不正确,因为它无需任何模拟即可工作。public class HelloworldcontrollerTest { private Helloworldcontroller hcontroller = new Helloworldcontroller(); @Test public void testGreeting() { String h = hcontroller.sayHelloSB(); Assert.assertEquals(h, "Hello,somebody"); }}无论如何,可能只是一个样本。嘲讽的问题在于这条线hservice_mock = Mockito.spy(hservice);首先,让Mockito创建您的模拟(@Mock Helloworldservice hservice_mock)并将其注入到控制器(@InjectMocks Helloworldcontroller hcontroller)中,然后您自己创建一个间谍(hservice_mock = Mockito.spy(hservice)),并尝试为其设置期望值()。为间谍建立期望值需要不同的方法调用链,因此当前会出现when(hservice_mock.greetingSB(...))(请参见Important gotcha on spying real objects!)。即使它可以工作,也不会影响已经注入的模拟。这将按预期工作:@RunWith(MockitoJUnitRunner.class)public class HelloworldcontrollerTest { @InjectMocks private Helloworldcontroller hcontroller = new Helloworldcontroller(); @Mock private Helloworldservice hservice_mock; @Before public void setup() { Mockito.when(hservice_mock.greetingSB(any(Map.class))) .thenReturn("Hello, somebody!!!"); } @Test public void testGreeting() { String h = hcontroller.sayHelloSB(); Assert.assertEquals(h, "Hello, somebody!!!"); }}关于测试设置的其他一些评论:NullPointerException依赖于Helloworldcontroller。与其在构造函​​数中创建实例,不如考虑使用构造函数依赖注入。您的示例代码可以正常工作,但是如果变得更加复杂,事情就会失去控制。想想数据库访问。Helloworldservice是代码异味的迹象,表示要测试的代码存在更深层的问题。尽量避免。@InjectMocks中的assertEquals第一个参数是期望值,然后是实际值。听起来不是很重要,但是会影响断言违反错误消息。让我们解决这些问题,看看如何改进代码。首先,使用构造函数注入。public class Helloworldcontroller { private final Helloworldservice hservice; public Helloworldcontroller(Helloworldservice hservice) { this.hservice = hservice; } public String sayHello() { return hservice.greeting(); } public String sayHelloSB() { Map<String, String> sb = new HashMap<String, String>(); sb.put("name", "somebody"); return hservice.greetingSB(sb); }}测试代码现在变成@RunWith(MockitoJUnitRunner.class)public class HelloworldcontrollerTest { private Helloworldcontroller hcontroller; @Mock private Helloworldservice hservice; @Before public void setup() { hcontroller = new Helloworldcontroller(hservice); Mockito.when(hservice.greetingSB(any(Map.class))) .thenReturn("Hello, somebody!!!"); } @Test public void testGreeting() { Assert.assertEquals("Hello, somebody!!!", hcontroller.sayHelloSB()); }}
09-26 01:11