Spring-如何使用ApplicationEventPublisher依赖项测试控制器?
我有一个正在发布事件的控制器Spring-如何使用ApplicationEventPublisher依赖项测试控制器?,spring,spring-boot,testing,event-handling,Spring,Spring Boot,Testing,Event Handling,我有一个正在发布事件的控制器 @RestController public class Controller { @Autowired private ApplicationEventPublisher publisher; @GetMapping("/event") public void get() { publisher.publishEvent(new Event()); } } 现在我想测试事件是否已发布。首先,我尝试
@RestController
public class Controller
{
@Autowired
private ApplicationEventPublisher publisher;
@GetMapping("/event")
public void get()
{
publisher.publishEvent(new Event());
}
}
现在我想测试事件是否已发布。首先,我尝试使用ApplicationEventPublisher@MockBean并验证方法调用。但这并不能根据实际情况发挥作用
所以我是这样做的:
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = Controller.class)
public class ControllerTest
{
@Autowired
private MockMvc mockMvc;
@Test
public void getTest() throws Exception
{
this.mockMvc.perform(get("/").contentType(MediaType.APPLICATION_JSON)
.andExpect(status().isOk());
assertNotNull(Listener.event);
}
@TestConfiguration
static class Listener
{
public static Event event;
@EventListener
void listen ( Event incoming )
{
event = incoming;
}
}
}
对于这个常用用例,有没有更简单的方法?您可以这样做
@RunWith(SpringRunner.class)
public class ControllerTest {
private MockMvc mockMvc;
@MockBean
private ApplicationEventPublisher publisher;
@Before
public void setup() {
Controller someController= new Controller(publisher);
mockMvc = MockMvcBuilders.standaloneSetup(someController).build();
}
@Test
public void getTest() throws Exception
{
ArgumentCaptor<Event> argumentCaptor = ArgumentCaptor.forClass(Event.class);
doAnswer(invocation -> {
Event value = argumentCaptor.getValue();
//assert if event is correct
return null;
}).when(publisher).publishEvent(argumentCaptor.capture());
this.mockMvc.perform(get("/").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(publisher, times(1)).publishEvent(any(Event.class));
}
}
另一种可能性是在测试中使用反射将控制器上的ApplicationEventPublisher实例替换为模拟实例:
public class ControllerTest {
...
// Collect your controller
@Autowired
private Controller controller;
// Use the mock publisher
@MockBean
private ApplicationEventPublisher publisherMock;
// E.g. in setup set the mock publisher on your controller
@Before
public void setup() {
ReflectionTestUtils.setField(controller, "publisher", publisherMock);
}
...
这是一个非常好的方法。我不知道:
mockMvc=MockMvcBuilders.standaloneSetup(someController.build()代码>只是这一部分有点烦人:@SpringBootTest
中的classes=MockServletContext.class
。是否没有内置注释来启用此行为?@davidxxx实际上根本不需要它。即使没有它,它也能工作。编辑了我的回答,这样更好。好吧,关键是手动将模拟发布者注入控制器。所以您不需要MockBean,只需要Mock annotation.ya,@Mock
就足够了。我们必须这样做,因为你已经提到的错误
public class ControllerTest {
...
// Collect your controller
@Autowired
private Controller controller;
// Use the mock publisher
@MockBean
private ApplicationEventPublisher publisherMock;
// E.g. in setup set the mock publisher on your controller
@Before
public void setup() {
ReflectionTestUtils.setField(controller, "publisher", publisherMock);
}
...