【问题标题】:How to write junit test for Postmapping method如何为 Postmapping 方法编写 junit 测试
【发布时间】:2020-04-13 10:47:27
【问题描述】:

我有一个程序,它显示带有名称的字段,用户需要输入它们。我该如何测试?

User.java - 用户类。

public class User {
    @NotEmpty
    private String firstName;

    @NotEmpty
    private String lastName;

public String getAllInfo() {
        return this.firstName + '\n' + this.lastName;
    }

//getters and setters

}

Store.java - 我的控制器类。

public class Store {

...

@PostMapping("/cart/index")
    public String getInfo(@Valid final User user, final Model model) {
        Store.LOGGER.info("{}", user.getAllInfo());
        return "cart/index";
    }

@GetMapping(value = "cart/index")
    public String index(final Model model) {
        model.addAttribute("user", new User());
        return "cart/index";
    }

...
}

我的 junit 测试现在失败,我收到以下消息。

null
null
MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /cart/index
       Parameters = {}
          Headers = {Accept=[application/json]}

Handler:
             Type = app.vlad.store.Store
           Method = public java.lang.String app.vlad.store.Store.getInfo(app.vlad.user.User,org.springframework.ui.Model)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = cart/index
             View = null
        Attribute = user
            value = app.vlad.user.User@248deced
           errors = []

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {}
     Content type = null
             Body = 
    Forwarded URL = cart/index
   Redirected URL = null
          Cookies = []

java.lang.AssertionError:JSON 路径“$.firstName”处没有值,异常:json 不能为 null 或为空

我的测试:

StoreTest.java

public class StoreTest {

    @Autowired
    MockMvc        mockMvc;

    @Mock
    private User   user;
    @Mock
    private Model  model;
    @Mock
    Store          store;

    @Autowired
    List<Products> products;

    @Before
    public void setup() {

        MockitoAnnotations.initMocks(this);
        final Store store = new Store(this.products);

        this.mockMvc = MockMvcBuilders.standaloneSetup(store).build();

    }
@Test
    public void testGetInfo() throws Exception {
        this.user.setFirstName("Ivan");
        this.user.setLastName("Ivanov");

        this.mockMvc
                .perform(MockMvcRequestBuilders.post("/cart/index")
                        .accept(MediaType.APPLICATION_JSON))
                .andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.firstName").value("Ivan"))
                .andExpect(MockMvcResultMatchers.jsonPath("$.lastName").value("Ivanov"));

    }
}

【问题讨论】:

  • 有几种方法,你试过了吗?

标签: java spring junit


【解决方案1】:

最好的方法是使用 SpringBootTest。 这将启动一个 Spring Boot 应用程序,然后您可以使用 RestAssured 之类的东西来调用 API。

本网站详细介绍了所有设置:http://www.masterspringboot.com/getting-started/testing-spring-boot/testing-spring-boot-with-rest-assured

【讨论】:

    【解决方案2】:

    一个简单的解决方案来测试你的具有验证的类,即上面示例中的用户类与简单的 Junit 可能是

    在你的 Junit 类中

    //The Class in spring which validates the annotations e.g @Notnull
    import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
    
     //Declare the field of this class into your test class
     private LocalValidatorFactoryBean localValidatorFactory;
    
    //Initialize the bean in Before test here I have used Hibernate Validator Implementation 
    @Before
    public void setup() {
        localValidatorFactory = new LocalValidatorFactoryBean();
        localValidatorFactory.setProviderClass(HibernateValidator.class);
        localValidatorFactory.afterPropertiesSet();
    }
    
    //Inside your test method use the Local validator
    @Test
      public void testNullValidationError() {
            final User user = new Use ();
            user.setfirstName(null);
            user.setLastName(null);
            Set<ConstraintViolation<User>> constraintViolations =      localValidatorFactory.validate(user);
            Assert.assertTrue("Your error message", constraintViolations.notNull == null);
        } 
    

    如果您想测试您的 API,那么您可以更好地使用 Spring MockMvc

    就是为了这个目的。 一些有用的示例代码 你需要运行你的使用

    @RunWith(SpringJUnit4ClassRunner.class)
    
            //You have to inject the Spring MockMvc which can redirect the request URL to your method.
    
            @Inject
            MockMvc mvc;
        //Intialize the Mock server before test execution
        @Before 
        public void init(){
        MockMvcBuilders.standaloneSetup(new Store()).build(); //I am assuming Store is ur controller Class
    
        inside ur test 
        you can do something lik e
    
        MvcResult result = mvc.perform(post(url).
                        contentType(MediaType.APPLICATION_JSON).
                        content(toJson(registration))).
                        andExpect(status().isBadRequest()).
                        andExpect(content().contentType(MediaType.APPLICATION_JSON)).
                        andReturn();
        }
    

    【讨论】:

      【解决方案3】:

      试试这个

      @Autowired
      private MockMvc mvc;
      
      @Test
      public void testGetInfo() {
          @Mock
          private User user;
          @Mock
          private Model model;
          @Mock
          private Store store;
      
          user.setFirstName("Test");
          user.setLastName("User");
      
          mvc.perform( MockMvcRequestBuilders
                  .post("/cart/index")
                  .accept(MediaType.APPLICATION_JSON))
                  .andDo(print())
                  .andExpect(status().isOk())
                  .andExpect(MockMvcResultMatchers.jsonPath("$.firstName").value("Test"))
                  .andExpect(MockMvcResultMatchers.jsonPath("$.lastName").value("User"));
      
      }
      

      【讨论】:

      • 不起作用:\ java.lang.AssertionError: Status expected: but was:
      • @VladStarostenko 你能把请求正文打印在控制台上吗
      • 我刚刚附在我的帖子里
      【解决方案4】:

      您可以使用@WebMvcTest 来实现。

      看下面的例子:

      @RunWith(SpringRunner.class)
      @WebMvcTest(YourController.class)
      public class YourControllerTest {
      
          @Autowired MockMvc mvc;
          @MockBean EmployeeService employeeService;
      
          @Test
          public void testPostMapping() throws Exception {
      
              YourRequestModel request = createRequestForPostMethod();
      
              mvc.perform(post("/cart/index")
      
      
            .contentType(MediaType.APPLICATION_JSON)
                      .content(toJson(request)))
                      .andExpect(status().isOk())
      .andExpect(jsonPath("$.firstName", is("yourExpectedOutput")));
              }
      

      在上面的代码中,您可以使用@MockBean 模拟您的依赖服务。 测试将在您的自定义 Employee 对象上执行发布并验证响应

      可以在调用perform时添加headers、授权

      假设您使用 JSON 作为媒体类型,您可以使用任何 json 库编写 toJson() 方法将 Employee 对象转换为 Json 字符串格式

      private String toJson(YourRequestModel yrm) {...}
      

      如果你使用的是 XML,那么你可以对 XML 做同样的事情

      您可以使用 $.firstName 或您拥有的任何合同以链式方式使用期望来验证响应。

      如果您有任何疑问,请告诉我。

      【讨论】:

      • 谢谢库纳尔!我刚刚尝试过,但现在我收到一个错误“JSON 路径没有值”。我在上面更新了。
      • 我没有看到您将用户对象作为发布数据传递。这就是输出为空的原因。在调试模式下尝试。参见代码“.content(toJson(request)))”。正如我在答案中所示,您需要将 post 对象作为 json 传递。如果您仍有疑问,请告诉我。
      猜你喜欢
      • 2023-02-17
      • 2019-11-01
      • 2022-11-18
      • 2021-02-03
      • 2022-11-04
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多