用Mockito在REST控制器中模拟类
我有一个通过控制器公开REST接口的spring-boot应用程序。这是我的控制器的例子:用Mockito在REST控制器中模拟类
@RestController
public class Controller {
@Autowired
private Processor processor;
@RequestMapping("/magic")
public void handleRequest() {
// process the POST request
processor.process();
}
}
我试图为此类编写单元测试,我必须嘲笑处理器(因为处理需要很长的时间,我试图避免在测试过程中这一步控制器行为)。请注意,为了解决这个问题,提供的示例被简化了。
我想使用的Mockito框架完成这个任务:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = App.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
Processor processor = Mockito.mock(Processor.class);
ReflectionTestUtils.setField(Controller.class, "processor", processor);
}
@Test
public void testControllerEmptyBody() throws Exception {
this.mockMvc.perform(post("/magic")).andExpect(status().isOk());
}
}
然而,这种失败
java.lang.IllegalArgumentException: Could not find field [processor] of type [null] on target [class org.company.Controller]
at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:112)
...
能否请人给我一个提示,如何模拟可能在注入我的控制器?
你不是应该通过一个实例来设置字段,而不是类,例如:
...
@Autowired
private Controller controller;
...
@Before
public void setUp() throws Exception {
...
Processor processor = Mockito.mock(Processor.class);
ReflectionTestUtils.setField(controller, "processor", processor);
}
我认为你可以直接注入像模拟:
@InjectMocks
private ProcessorImpl processorMock;
并删除这一行:
ReflectionTestUtils.setField(Controller.class, "processor", processor);
尝试使用injectMocks注释,但它不起作用(原始处理器被调用)。甚至试图将其命名为与控制器内部的字段名称相同... – Smajl
@Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
Processor processor = Mockito.mock(Processor.class);
//This line should be added to perform mock for Processor.
Mockito.when(processor.process()).thenReturn(<Your returned value>);
//ReflectionTestUtils.setField(Controller.class, "processor", processor);
}
在上面放置您的返回值为“您的返回值”并在测试中使用此值验证您的输出。
重做您的控制器以使用构造函数注入而不是字段注入。这使得依赖性显式化并使测试设置极其简单。
您可以删除SpringApplicationConfiguration
和模拟servlet上下文中的servlet上下文类。不需要注入WebApplicationContext
和ReflectionTestUtils
。
基本上,你的代码应该是这个样子:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class ControllerTest {
@InjectMocks
private MyController controller;
@Mock
private Processor processor;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void testControllerEmptyBody() throws Exception {
when(proessor.process()).thenReturn(<yourValue>);
this.mockMvc.perform(post("/magic")).andExpect(status().isOk());
verify(processor, times(<number of times>)).process();
}
}
Processor
会被嘲笑和模仿将被注入到控制器。
有趣的...并没有出现在我身上,我也可以自动连接控制器。谢谢。奇迹般有效! – Smajl