【问题标题】:Spring MVC Mockito Test returning 406 error instead of 200Spring MVC Mockito 测试返回 406 错误而不是 200
【发布时间】:2020-11-21 22:10:33
【问题描述】:

所以我正在使用一个有效的 UI,并使用一个 DB2 数据库。我正在尝试在控制器/服务/dao 层上运行单元测试,并且正在使用 mockito 和 junit 进行测试。以下是每一层的部分:

Measures.java

@Controller
@RequestMapping(value = "/measures"})
public class Measures {

    @Resource
    private CheckUpService checkUpService;
    
    public void setCheckUpService(CheckUpService checkUp) {
        this.checkUpService = checkUpService;
    }    

    @RequestMapping(value = "/eligibility/{userId}/{effDate}/{stageInd}", method = RequestMethod.POST, produces = "application/json")
    public @ResponseBody List<Model> findEligibility(@PathVariable int userId, @PathVariable String effDate, @PathVariable String stageInd) throws Exception
    {
        List<Model> result = new ArrayList<Model>();

        if (stageInd.equals("stage"))
        {
            result = checkUpService.findEligibilityStage(userId, effDate);
        }

        if (stageInd.equals("prod"))
        {
            result = checkUpService.findEligibility(userId, effDate);
        }

        return result;
    }
...
}

CheckUpService.java

public class CheckUpService {

    @Resource
    EligibilityDao eligDao;

    public List<Model> findEligibility(int userId, String effDate) throws Exception
        {
             return eligDao.findEligibility(userId, effDate, db_table);
        }
}

EligibilityDao.class

public class EligibilityDao {

    public List<Model> findEligibility(int userId, String effDate, String table) throws Exception
        {
            // uses some long sql statement to get some information db2 database and 
            // jdbctemplate helps return that into a list.
        }
}

这是我正在尝试做的控制器测试,我已经花了大约 10 个小时在这上面,我真的不明白为什么它给了我 406 错误而不是 200。

ControllerTest.java

@EnableWebMvc
@WebAppConfiguration
public class ControllerTest {
    
    @Autowired
    private Measures measures;
    
    @Autowired
    private WebApplicationContext webApplicationContext;
    
    private MockMvc mockMvc;
    
    private List<Model> findEligibility() {
        
        List<Model> list = new ArrayList<>();
        
        Model test_model = new Model();
        
        test_model.setUserId(99);
        test_model.setCreateID("testUser");
        test_model.setEffDate("2020-07-30");
        
        list.add(test_model);
        
        return list;
    }
    
    @Before
    public void setup() throws Exception {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
    
    @Test
    public void test_find() throws Exception {
        
        CheckUpService checkUpService = mock(CheckUpService.class);
        
        when(checkUpService.findEligibility(99, "2020-07-30")).thenReturn(findEligibility());
        
        measures.setCheckUpService(checkUpService);
        
        String URI = "/measures/eligibility/99/2020-07-30/prod";
        
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
        
        MvcResult handle = mockMvc.perform(requestBuilder).andReturn();

//      MvcResult handle = mockMvc.perform(requestBuilder).andExpect(status().isOk()).andReturn();

        MvcResult result = mockMvc.perform(asyncDispatch(handle)).andExpect(status().isOk()).andReturn();
        
//      assertThat(result.getResponse().getContentAsString()).isEqualTo(findEligibility()); 

    }
    
    
    
}

MvcResult 结果是在 junit 中抛出“StatusExpected 但为 ”错误的原因,我对它的原因感到很生气。另一个问题是,如果你能看到,我用 .andExpect(status().isOk()) 注释掉了句柄,并且那个也抛出了同样的问题。是我设置的测试有问题还是什么?

【问题讨论】:

    标签: java spring spring-boot spring-mvc junit


    【解决方案1】:

    我无法重现您的问题。但是,我得到了这个工作。

    因此,Controller 没有大的变化,但我删除了字段注入以支持构造函数注入。

    @Controller
    @RequestMapping(value = "/measures")
    public class Measures {
    
        private final CheckUpService checkUpService;
    
        public Measures(CheckUpService checkUpService) {
            this.checkUpService = checkUpService;
        }
    
        @RequestMapping(value = "/eligibility/{userId}/{effDate}/{stageInd}", method = RequestMethod.POST, produces = "application/json")
        public @ResponseBody List<Model> findEligibility(@PathVariable int userId, @PathVariable String effDate, @PathVariable String stageInd) throws Exception {
            List<Model> result = new ArrayList<>();
    
            if (stageInd.equals("stage")) {
                result = checkUpService.findEligibility(userId, effDate);
            }
    
            if (stageInd.equals("prod")) {
                result = checkUpService.findEligibility(userId, effDate);
            }
    
            return result;
        }
    }
    

    服务类也是如此。

    @Service
    public class CheckUpService {
    
        private final EligibilityDao dao;
    
        public CheckUpService(EligibilityDao dao) {
            this.dao = dao;
        }
    
        public List<Model> findEligibility(int userId, String effDate) throws Exception {
            return dao.findEligibility(userId, effDate, "demo value");
        }
    }
    
    

    这是测试。我没有初始化 MockMvc 并注入 Web 上下文,而是注入了 MockMvc。此外,使用@MockBean,您可以注入模拟。因此,我将模拟创建从测试方法中删除到了初始化部分。

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    public class MeasuresTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @MockBean
        private CheckUpService service;
    
        @Test
        public void test_find() throws Exception {
            Model model = new Model(99, "2020-08-02", "2020-07-30");
            when(service.findEligibility(99, "2020-07-30"))
                    .thenReturn(Collections.singletonList(model));
            String URI = "/measures/eligibility/99/2020-07-30/prod";
    
            MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI)
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON);
    
            final MvcResult mvcResult = mockMvc.perform(requestBuilder)
                    .andExpect(status().isOk()).andReturn();
    
            final String json = mvcResult.getResponse().getContentAsString();
    
            final List<Model> models = new ObjectMapper().readValue(json, new TypeReference<>() {
            });
    
            Assert.assertEquals(1, models.size());
            Assert.assertEquals(model, models.get(0));
        }
    }
    

    在帖子中,我找不到你使用asyncDispatch的任何理由,所以我没有使用它。

    【讨论】:

    • 当我尝试这个时,我在 "when(service.findEligibility(99, "2020-07-30")).thenReturn(Collections.singletonList(model));" 上得到一个 NPE当我调试它时,我看到 CheckUpService 出于某种原因为空?
    • 上面有@Service注解吗?
    • 是的,它的顶部有@Service
    • 您使用的是什么版本的 Mockito、Spring boot 和 Junit?
    • 我认为 spring boot 是 3.8,Mockito 是 4.10,junit 是 4
    猜你喜欢
    • 2011-05-03
    • 2018-04-27
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 2016-03-11
    相关资源
    最近更新 更多