Java Spring Softwaretest json 响应为空。为什么?

问题描述 投票:0回答:1

我正在开发一个有趣的项目,其中包含一些随机人员数据(来自java-faker),以了解有关 java、spring、api、thymeleaf、软件测试的更多信息...

-> 来自 gitlab 的我的项目

除了许多小问题之外,junit、spring、mockmvc 的软件测试正在运行,但无法正常工作。带有分支
junit-test-and-post-request
的代码将使用
mockmvc
连接到 api 和控制器,但生成的 json 响应为空。 我尝试并复制了其他人的许多其他解决方案和想法,他们用或多或少相似的代码展示了他们的方法,但所有这些都不适合我:(也许某个地方使用了错误的注释或错误的库版本。

带有测试代码的文件内容(请忽略嵌套类):

package com.example.demo;

import com.example.demo.controller.PersonController;
import com.example.demo.service.PersonService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.event.annotation.AfterTestClass;
import org.springframework.test.context.event.annotation.BeforeTestClass;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

//@ExtendWith(SpringExtension.class)
//@WebMvcTest(PersonController.class)
@AutoConfigureMockMvc
@SpringBootTest
public class PersonTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private PersonService personService;

    @MockBean
    private PersonController personController;

    static final String url = "http://localhost:8000";

    static final String urlCreateData = "http://localhost:8000/createMoreData?username=admin&pw=secret";

    private static final Logger log = LoggerFactory.getLogger(PersonTest.class);

    @Test
    @ResponseBody
    @DisplayName("1st lvl: basic request, get status http.ok")
    public void testRequest() throws Exception {
        log.info("1st lvl: basic request, get status http.ok");
        mockMvc.perform(MockMvcRequestBuilders
                .get(url)
                .accept(MediaType.APPLICATION_JSON))
                //.andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.status().isOk())
                ;
        createWebsiteData();
    }

    private void createWebsiteData() throws Exception {
        log.info("Create data with db:");
        mockMvc.perform(MockMvcRequestBuilders
                        .post(urlCreateData)
                        .accept(MediaType.APPLICATION_JSON))
                .andDo(MockMvcResultHandlers.print());
    }

    @Test
    @ResponseBody
    @DisplayName("Next lvl: basic request, get status http.ok, get json response with data path.")
    public void testRequestWithJson() throws Exception {
        log.info("Next lvl: basic request, get status http.ok, get json response with data path.");
        log.info("Result:");
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders
                .get(url)
                .accept(MediaType.APPLICATION_JSON)
                .characterEncoding("utf-8"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$."+personService.NAME_FOR_MODEL_DATA).exists())
                .andReturn();
    }

    @AfterTestClass
    @DisplayName("End -> Clean")
    public void clean() {
        log.info("End -> Clean");
    }
    @Nested
    class Start {

        @Test
        @DisplayName("Next lvl -> tell program to create data")
        public void testCallMethod(){
            log.info("Next lvl -> tell program to create data");
        }

        @Test
        @DisplayName("PersonTest Json:model exists")
        public void testJsonPersonsExist() {
            log.info("PersonTest Json:model exists");
        }

        @Nested
        class IfExists {

            @Test
            @DisplayName("PersonTest Json:model is an array & is not empty")
            public void TestJsonPersonsListIsNotEmpty() {
                log.info("PersonTest Json:model is an array & is not empty");
            }

            @Test
            @DisplayName("PersonTest Json:abc does not exist")
            public void TestJsonWrongPersonsDoNotExist() {
                log.info("PersonTest Json:abc does not exist");
            }
            @Test
            @DisplayName("Test1 Json:abc does not exist")
            public void TestJsonWrongPersonsDoNotExist1() {
                log.info("PersonTest Json:abc does not exist");
            }

            @Test
            @DisplayName("PersonTest Json:model[].id exists")
            public void TestJsonPersonsIdExist() {
                log.info("PersonTest Json:model[].id exists");
            }
        }
    }
}

控制器文件内容:

package com.example.demo.controller;

import com.example.demo.entity.Person;
import com.example.demo.repository.PersonRepository;
import com.example.demo.service.PersonService;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

import static com.example.demo.service.PersonService.*;

@RestController
//@Controller
//@RestController
//@RequestMapping("/index.html")
//@RequestMapping("/")
@RequestMapping("")
public class PersonController {

    private static final Logger log = LoggerFactory.getLogger(PersonController.class);

    @Autowired
    Environment environment;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    PersonRepository personRepository;

    @Autowired
    PersonService personService;

    final String htmlFile = "index";

    @PostMapping("/createMoreData")
    @ResponseStatus(code = HttpStatus.OK)
    public String createMoreData(
            @RequestParam(required = false) String username,
            @RequestParam(required = false) String pw,
            Model model,
            HttpServletResponse httpServletResponse){
        switch (isAdminAccount(username, pw)) {
            case YES -> {
                if(isDatabaseEmpty()) {
                    createNewData(true);
                    model.addAttribute("message",
                        "Created new data with admin account(s).");
                } else {
                    createNewData();
                    model.addAttribute("message",
                        "Created new data.");
                }
                model.addAttribute(personService.NAME_FOR_MODEL_DATA, getDataWithoutSensibleInfos(true, personRepository.findAll()));
                model.addAttribute(personService.NAME_FOR_MODEL_PERMISSION, true);
            }
            case EMPTY_PARAMETER -> {
                log.error(PersonService.IsAdmin.EMPTY_PARAMETER.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_MESSAGE,
                        "Did not create new data: " + PersonService.IsAdmin.EMPTY_PARAMETER.toString());
                httpServletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                model.addAttribute(personService.NAME_FOR_MODEL_DATA, getDataWithoutSensibleInfos(false, personRepository.findAll()));
                model.addAttribute(personService.NAME_FOR_MODEL_PERMISSION, false);
            }
            case WRONG_PARAMETER -> {
                log.error(PersonService.IsAdmin.WRONG_PARAMETER.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_MESSAGE,
                        "Did not create new data: " + PersonService.IsAdmin.WRONG_PARAMETER.toString());
                httpServletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                model.addAttribute(personService.NAME_FOR_MODEL_DATA, getDataWithoutSensibleInfos(false, personRepository.findAll()));
                model.addAttribute(personService.NAME_FOR_MODEL_PERMISSION, false);
            }
        }
        return htmlFile;
    }

    @GetMapping("")
    public String loadData(@RequestParam(required = false) String username, @RequestParam(required = false) String pw, Model model){
        if(personService.CREATE_DB_DATA_ON_STARTUP && isDatabaseEmpty()) {
            createNewData(true);
            model.addAttribute(personService.NAME_FOR_MODEL_MESSAGE,
                    "Created new data with admin account(s).");
        }
        switch (isAdminAccount(username, pw)) {
            case YES -> {
                log.info(IsAdmin.YES.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_DATA, getDataWithoutSensibleInfos(true, personRepository.findByIsAdminTrue()));
            }
            case EMPTY_PARAMETER -> {
                log.error(IsAdmin.EMPTY_PARAMETER.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_PERMISSION, false);
                model.addAttribute(personService.NAME_FOR_MODEL_MESSAGE, IsAdmin.EMPTY_PARAMETER.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_DATA, getDataWithoutSensibleInfos(false, personRepository.findByIsAdminFalse()));
            }
            case WRONG_PARAMETER -> {
                log.error(IsAdmin.WRONG_PARAMETER.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_PERMISSION, false);
                model.addAttribute(personService.NAME_FOR_MODEL_MESSAGE, IsAdmin.WRONG_PARAMETER.toString());
                model.addAttribute(personService.NAME_FOR_MODEL_DATA, getDataWithoutSensibleInfos(false, personRepository.findByIsAdminFalse()));
            }
        }
        //model.addAttribute("Person", viewPerson);
        return htmlFile;
    }
    private void createNewDataIfNotCreated(){
        if(isDatabaseEmpty()){
            List<Person> personList = createNewDataWithAdmin();
            log.info("Saving all "+personList.size()+" data to database.");
            personRepository.saveAll(personList);
        }
    }
    private void createNewData(){
        createNewData(false);
    }
    private void createNewData(boolean withAdmin){
        List<Person> personList = null;
        if(withAdmin) {
            personList = createNewDataWithAdmin();
        } else {
            personList = PersonService.createNewData();
        }
        log.info("Saving all " + personList.size() + " data to database.");
        personRepository.saveAll(personList);
    }
    private boolean isDatabaseEmpty(){
        return jdbcTemplate.queryForList("select * from " + personService.DATABASE_NAME + " limit 1;").isEmpty();
    }

}

错误消息如:注入库错误、缺少模板、jdbctemplate 位于错误的类中等等。 任何帮助,将不胜感激。 预先感谢。

java spring testing spring-restcontroller mockmvc
1个回答
0
投票

您定义的测试具有

@SpringBootTest
。由于您没有设置更多配置详细信息,因此 URL 可用性使用默认值。

来自文档

适用时要创建的 Web 环境类型。默认为 WebEnvironment.MOCK。

Mock 表示没有设置 URL 可用性。

© www.soinside.com 2019 - 2024. All rights reserved.