[alibaba/druid]Spring Test中使用MockMvc时,报NullPointerException

2023-12-08 649 views
0

Druid版本:1.1.3、1.1.4 配置如下(其他默认):

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/db
    username: username
    password: password

测试代码如下:

public class UserControllerTest  {
    @Resource
    private MockMvc mvc;

    @Test
    public void testGet() throws Exception {
        mvc.perform(get("/").accept(MediaType.APPLICATION_JSON_UTF8)).andExpect(status().isOk());
    }
}

错误如下:

java.lang.NullPointerException
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:94)
    at org.springframework.test.web.servlet.setup.PatternMappingFilterProxy.doFilter(PatternMappingFilterProxy.java:101)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:108)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    ……

回答

9

com.alibaba.druid.support.http.WebStatFilter#init 这个没有执行?

4

Mock 的方式貌似不能初始化 Filter,你可以使用下面这种方式来做单元测试~

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "hello druid";
    }
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class ControllerTest {
    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void test() {
        String result = this.restTemplate.getForObject("/hello", String.class);
        assertEquals(result, "\"hello druid\"");
    }
}
7

那么现在如果使用MockMvc来测试的话, 应该怎么做呢?

1

@kizimini 解决了没,没有的话可以试试单元测试中添加如下代码

    /**
     * web项目上下文
     */
    @Autowired
    private WebApplicationContext webApplicationContext;

    /**
     * 所有测试方法执行之前执行该方法
     */
    @Before
    public void before() {
        //获取mockmvc对象实例
        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

我这样就解决了问题啦

1

不行的, 这样做是不加载其他的过滤器. 这样权限校验无法通过

8

使用MockMvc测试时, WebStatFilter类其实是没有用的. 现在可用的解决方案是:

  1. 加入 druid-spring-boot-starter 依赖
  2. 在application-test.properties中增加配置spring.datasource.druid.web-stat-filter.enabled=false
  3. 在测试类上增加@ActiveProfiles("test")
8

不论将 application-test.properties 放到 main/resources 目录下还是 test/resources(已将该目录标记为测试资源目录) 目录下进行加载, 都无法避免 WebStatFilter.doFilter 造成的 NPE 异常.

main/resources/application-test.properties: src-application_test

test/resources/application-test.properties: test-application_test

使用 TestRestTemplate 进行单元测试的话确实是能够避免 WebStatFilter.doFilter 造成的 NPE 异常, 但是..但是..template 对象返回的都是LinkedHashMap 对象啊..这测试起来就难看了...

==2018/02/03== kizimini 的方案应该是对的.. 在main/recources/application.yaml中配置数据库,Druid相关内容 在main/recources/application.properties中配置日志输出相关内容 在test/recources/application.properties中禁用web-stat-filter就能够正常使用MockMVC进行测试了.

5

SpringBootTest注解默认使用 webEnvironment = WebEnvironment.MOCK,它是不会对Filter、Servlet进行初始化的。 显示设置 webEnvironment 如下即可: @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

3

可以在test的配置中这样设置: spring.datasource.druid.WebStatFilter.enabled=false

5

SpringBootTest注解默认使用 webEnvironment = WebEnvironment.MOCK,它是不会对Filter、Servlet进行初始化的。 显示设置 webEnvironment 如下即可: @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

这个方案是可以init filter了 但是mockmvc不走filter呀。_**.addFilter(new Filter)**_。如果new的话 还是没有init数据

2

SpringBootTest注解默认使用 webEnvironment = WebEnvironment.MOCK,它是不会对Filter、Servlet进行初始化的。 显示设置 webEnvironment 如下即可: @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

以上这个方法方式可以init filter ,在mockmvc 使用的时候需要从容器吧bean拿出来就可以了 @Autowired private WebApplicationContext webApplicationContext;

Filter f = (Filter)webApplicationContext.getbean("BeanName") mockmvc.perform(……) .addFilter(f).builder() 完美搞定 THX ALL