如何使用@AutoConfigureMockMVC仅打印失败测试的请求



在我们的项目中,我们将@AutoConfigureMockMvcprintOnlyOnFailure一起使用,默认为true

这可以正常工作,并且没有打印任何请求……除非有任何测试失败。那时,它从> >所有测试中打印 able 请求。尽管这有时可能很有用,但这可能会打印大量日志,如果它发生在我们的CI服务器上,则日志被截断了,我们甚至看不到哪个测试失败(因为后来打印了AssertionError

更糟:如果多个测试失败,则为每个失败测试打印所有先前的请求。

是否可以配置它,以使其仅打印失败测试的请求?

这是重现问题的样本测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MockMvcTest {
    @Autowired
    private MockMvc mockMvc;
    @Test
    public void successfulTest() throws Exception {
        mockMvc.perform(get("/successfulTest"))
                .andExpect(status().isNotFound());
    }
    @Test
    public void failingTest() throws Exception {
        mockMvc.perform(get("/failingTest"))
                .andExpect(status().isOk());
    }
    @Test
    public void failingTest2() throws Exception {
        mockMvc.perform(get("/failingTest2"))
                .andExpect(status().isOk());
    }
    @Configuration
    static class TestApplication {
    }
}

我们使用的是Spring-Boot 1.5.14和Java 8.我还以Spring-Boot 2.1.4。

从我能找到的,日志线存储在org.springframework.boot.test.autoconfigure.web.servlet.SpringBootMockMvcBuilderCustomizer.DeferredLinesWriter.lines中,永远不会重置,也似乎没有一种重置方法 - 我宁愿避免通过反射进行。

<</p>

所以我试图进一步研究SpringBootMockMvcBuilderCustomizer实现,并且一切似乎都是privateprotected,以防止重复使用任何内容(甚至不确定您可以重复使用PrintingResultHandler本身,由于唯一的构造函数是protected(。

使用反射并不难,将其添加到测试中:

@Autowired
private ApplicationContext context;
private Runnable linesWriterClearer;
@PostConstruct
public void initLinesWriterClearer() throws NoSuchFieldException, IllegalAccessException {
    Object linesWriter = context.getBean("org.springframework.boot.test.autoconfigure.web.servlet.SpringBootMockMvcBuilderCustomizer$DeferredLinesWriter");
    Field linesField = linesWriter.getClass().getDeclaredField("lines");
    linesField.setAccessible(true);
    List<?> lines = (List<?>) linesField.get(linesWriter);
    linesWriterClearer = lines::clear;
}
@Before
public void clearLinesWriter() {
    linesWriterClearer.run();
}

不是很干净,可能会在未来版本的Spring Boot中破裂,但它起作用。

我希望能够实施更好的解决方案,但恐怕这是不可能的。

我不确定是否有人对此感兴趣,但我记得几年前,我在另一个非春季启动项目上,可能是在引入printOnlyOnFailure选项之前真正了解为什么它在v5.0.5上打印了以前执行的测试(我尚未测试更高版本(

就像您一样,我今天需要回到一个较新的项目上,花了几个小时才提醒我是如何做到的,我想我也发现了stackoverflow上的最初想法,所以这是一个简短的答案,试图将其复活。好主意(我目前不在来源前面,但可以随意询问实施,只需使用junit4或junit5而没有反思(

(

简短答案:

  • 注册junit5 testwatcher
  • 覆盖testFailed()方法
  • 当您的Junit测试执行时,存储MockMVC结果
  • 失败,致电print().handle(result.andReturn())
  • @AutoConfigureMockMvc(print = MockMvcPrint.NONE)
  • 注释您的测试摘要/配置

结果是保存的最后一个测试失败的实例。

不利的一面是您必须像这样写测试

result = mvc
    .perform();
result
    .andExpect()
    .andExpect();

不是完美的,但是我发现这种方式比使用反射更优雅:(

最新更新