【问题标题】:@WebMvcTest Found Status 404 And Service return null@WebMvcTest 发现状态 404 并且服务返回 null
【发布时间】:2019-11-10 03:59:39
【问题描述】:

当我使用@WebMvcTest 测试我的 Spring Controller 时,我遇到了两个问题。

  1. MockMvc 找不到正确的 URL
  2. 在我添加MockMvcBuilders.standaloneSetup() 后,mockMvc 工作了。但是我的控制器throw NullPointException caused by @Autowired Service

我只是做单元测试,所以我不想使用@SpringBootTest 来启动我所有的 SpringBoot 应用程序。 我试过@InjectMock我的控制器和@Mock or @MockBean服务。都没有工作。 那么有人可以告诉我为什么@Autowired mockMvc 找不到控制器以及如何在没有@SpringBootTest 的情况下模拟在Spock 单元测试中提交的内部@Autowired

这是我的控制器

@RestController
@RequestMapping("/schedule/filter")
public class ScheduleObjectFilterController extends BaseController {
    @PostMapping(path="/",produces  = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String createScheduleObjectFilter(@RequestBody String body){
        BaseResponse<ResponseStatus> resp = new BaseResponse<>(ResponseStatus._200);
        try{
            List<ScheduleObjectFilterParam> paramList = parseJSONArray(body,ScheduleObjectFilterParam.class);
            resp.setStatus(scheduleObjectFilterService.createScheduleObjectFilter(paramList));
        }catch(BaseRuntimeException e){
            logger.error("Create ScheduleObjectFilter error:", e);
            resp.setException(e);
        }catch(Exception e){
            logger.error("Create ScheduleObjectFilter error:", e);
            resp.setStatus(ResponseStatus._500);
        }
         return renderJSON(resp);
    }

    @Autowired
    private ScheduleObjectFilterService scheduleObjectFilterService;

}

这是我的服务,它正在实施

public interface ScheduleObjectFilterService{
     ResponseStatus createScheduleObjectFilter(List<ScheduleObjectFilterParam> paramList);
}
@Service
public class ScheduleObjectFilterServiceImpl extends BaseService implements ScheduleObjectFilterService {
    public ResponseStatus createScheduleObjectFilter(List<ScheduleObjectFilterParam> paramList) {
    // some code
    }
}

这是我的测试课

@WebMvcTest(controllers = [ScheduleObjectFilterController.class])
@ActiveProfiles("local")
class ScheduleSettingControllerSpecification extends Specification{

    @Autowired
    MockMvc mockMvc

    @MockBean
    BaseController baseController

    @MockBean
    ScheduleObjectFilterService scheduleObjectFilterService

    def setup(){
        //after add next line,the mockMvc can find url,but service throw NullPointException
        //mockMvc = MockMvcBuilders.standaloneSetup(new ScheduleObjectFilterController()).build()
        scheduleObjectFilterService.createScheduleObjectFilter(_ as List) >> ResponseStatus._500
    }

    def "MvcTest"(){
        given:
        ScheduleObjectFilterParam param = new ScheduleObjectFilterParam()
        List<ScheduleObjectFilterParam> dataList = Collections.singletonList(param)
        expect:
        mockMvc.perform(post("/schedule/filter/").contentType(MediaType.APPLICATION_JSON).content(JSONObject.toJSONString(dataList)))
        .andExpect(status().isOk())
    }

}

在添加MockMvcBuilders.standaloneSetup()之前:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /schedule/filter/
       Parameters = {}
          Headers = {Content-Type=[application/json]}
             Body = <no character encoding set>
    Session Attrs = {}

Handler:
             Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 404
    Error message = null
          Headers = {}
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

添加之后:

2019-11-10 11:53:22.896 [WEB] [ERROR] com.kaifa.hes.schedule.controller.ScheduleObjectFilterController.createScheduleObjectFilter() -> Create ScheduleObjectFilter error:
java.lang.NullPointerException: null
    at com.kaifa.hes.schedule.controller.ScheduleObjectFilterController.createScheduleObjectFilter(ScheduleObjectFilterController.java:47) [classes/:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_201]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_201]
......

这个异常直接指向控制器中的这一行

resp.setStatus(scheduleObjectFilterService.createScheduleObjectFilter(paramList));

【问题讨论】:

  • 您还必须添加模拟服务,在scheduleObjectFilterService 上添加@MockBean@WebMvcTest 只是为了测试像控制器这样的 web 层
  • 谢谢你的回答。我之前加过,但还是抛出NullPointException

标签: spring-boot mockito spock


【解决方案1】:

@WebMvcTest 仅用于通过应用程序测试 Web 层,因此您需要在控制器中模拟任何依赖项并 stub 方法调用。 more information

@WebMvcTest(controllers = [ScheduleObjectFilterController.class])
@ActiveProfiles("local")
class ScheduleSettingControllerSpecification extends Specification{

@Autowired
MockMvc mockMvc

@MockBean
BaseController baseController

@MockBean
ScheduleObjectFilterService  scheduleObjectFilterService


def "MvcTest"(){

    when(this.scheduleObjectFilterService.createScheduleObjectFilter(ArgumentMatchers.anyList())
     .thenReturn(// custom error);    

    given:
    ScheduleObjectFilterParam param = new ScheduleObjectFilterParam()
    List<ScheduleObjectFilterParam> dataList = Collections.singletonList(param)
    expect:mockMvc.perform(post("/schedule/filter/").contentType(MediaType.APPLICATION_JSON).content(JSONObject.toJSONString(dataList)))
    .andExpect(status().isOk())
   }

}

【讨论】:

  • 谢谢你的回答。我之前加过,但还是抛出NullPointException
  • 好的,我已经完成了。但是,在我阅读的一些博客中,Spock 中的 def obj = Mock(SomeClass) 似乎与@MockBean SomeClass someClass 一样。我不知道我是否真的了解他们之间的关系。
  • 您还应该使用whengiven @New_Code 对模拟对象的方法进行存根
  • 谢谢。我已经知道导致 NullPointException 的真正原因。 Spock 不支持 @InjectMocks 注解。所以如果我想使用同样的功能,我应该使用第三方 Spock 扩展喜欢github.com/marcingrzejszczak/…
【解决方案2】:

@InjectMocks 不能在 Spock 中工作。如果我们想使用相同的功能,这里有一个third-part extension 我们可以使用@Subject 和@Collaborator 注解来解决这个问题。 注意,Spock有自己的@Subject注解。在导入包之前,请检查是否在正确的包中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2017-06-15
    • 2020-01-28
    • 2011-11-22
    相关资源
    最近更新 更多