我有一个spring-boot应用程序,它通过控制器公开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)
...
可以请某人给我一个提示,这个模拟怎么可以注入我的控制器?
答案 0 :(得分:4)
你不应该传递一个实例来设置字段而不是类,例如:
...
@Autowired
private Controller controller;
...
@Before
public void setUp() throws Exception {
...
Processor processor = Mockito.mock(Processor.class);
ReflectionTestUtils.setField(controller, "processor", processor);
}
答案 1 :(得分:1)
我认为您可以直接注入模拟:
@InjectMocks
private ProcessorImpl processorMock;
并删除此行:
ReflectionTestUtils.setField(Controller.class, "processor", processor);
答案 2 :(得分:1)
重新设计控制器以使用构造函数注入而不是字段注入。这使得依赖项显式化并使您的测试设置更加简单。
答案 3 :(得分:0)
@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);
}
在上面,将您返回的值设为“您的返回值”,并在测试中使用此值来验证您的输出。
答案 4 :(得分:0)
您可以删除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
将被模拟,模拟将被注入控制器。