java ServletException,使用SpringBoot API时运行、测试和http请求之间的不同行为

wj8zmpe1  于 2023-02-07  发布在  Java
关注(0)|答案(1)|浏览(101)

我正在构建一个SpringBootAPI来学习这个框架,我面临着两个奇怪的问题,它们可能以某种方式联系在一起。
第一个问题,当我尝试使用自己的Junit测试类EmployeeControllerTest测试代码时,使用http请求调用方法会返回以下错误:jakarta.servlet.ServletException:请求处理失败:java.util.NoSuchElementException:无数值
第二个问题,当我用Postman执行这些测试时,返回雇员列表的请求/雇员工作得很好,但是请求/雇员(在url中添加或不添加id),API什么也不返回。
除此之外,从代码内部(在run类中)调用方法效果很好,我得到了我需要的每一个结果。
下面是涉及到的每个部分的代码。首先是模型类:

package com.openclassrooms.api.models;

import jakarta.persistence.*;

import lombok.Data;

@Data
@Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    private String mail;

    private String password;

}

存储库类:

package com.openclassrooms.api.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.openclassrooms.api.models.Employee;

@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Long> {

}

服务类别:

package com.openclassrooms.api.service;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.repository.EmployeeRepository;

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    public Optional<Employee> getEmployee(final Long id) {
        System.out.println("getEmployee ok");
        return employeeRepository.findById(id);
    }

    public Iterable<Employee> getEmployees() {
        System.out.println("getEmployees ok");
        return employeeRepository.findAll();
    }

    public void deleteEmployee(final Long id) {
        employeeRepository.deleteById(id);
    }

    public Employee saveEmployee(Employee employee) {
        Employee savedEmployee = employeeRepository.save(employee);
        return savedEmployee;
    }

}

和控制器类:

package com.openclassrooms.api.controller;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.service.EmployeeService;

@RestController
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    // Read - Get all employees

    // @return - An Iterable object of Employee full filled

    @GetMapping("/employees")
    public Iterable<Employee> getEmployees() {
        Iterable<Employee> list = employeeService.getEmployees();
        System.out.println(list);
        return list;
    }

    @GetMapping("/employee/{id}")
    public Employee getEmployee(@PathVariable("id") final Long id) {
        Optional<Employee> emp = employeeService.getEmployee(id);

        if (emp.isEmpty()) {
            Employee employe = emp.get();
            System.out.println(employe.getFirstName());
            return employe;
        } else {
            System.out.println("ABSENT");
            return null;
        }
    }

    @GetMapping("/employee")
    public Employee getEmployee() {
        Optional<Employee> emp = employeeService.getEmployee(1L);

        if (emp.isEmpty()) {
            Employee employe = emp.get();
            System.out.println(employe.getFirstName());
            return employe;
        } else {
            System.out.println("ABSENT");
            return null;
        }
    }
}

此外,主要类别和测试类别:

package com.openclassrooms.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.service.EmployeeService;

@SpringBootApplication
public class ApiApplication implements CommandLineRunner {

    @Autowired
    private EmployeeService employeeService;

    public static void main(String[] args) {

        SpringApplication.run(ApiApplication.class, args);
    }

    public void run(String... args) throws Exception {

        if (employeeService.getEmployee(1L).isPresent()) {

            Employee emp1 = employeeService.getEmployee(1L).get();
            System.out.println(emp1.getFirstName() + " " + emp1.getLastName());

        } else {
            System.out.println("Erreur, employé absent.");
        }

        System.out.println(employeeService.getEmployees());
    }

}
package com.openclassrooms.api;

import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;

import java.io.PrintStream;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
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.MediaType;
import org.springframework.test.web.servlet.MockMvc;
//import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.ResultHandler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.openclassrooms.api.controller.EmployeeController;
import com.openclassrooms.api.models.Employee;
import com.openclassrooms.api.service.EmployeeService;

//@SpringBootTest
//@AutoConfigureWebMvc
@WebMvcTest(controllers = EmployeeController.class)
public class EmployeeControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private EmployeeService employeeService;

    @Test
    public void testGetEmployees() throws Exception {
        Employee response = new Employee();

        mockMvc.perform(get("/employee"))
                .andExpect(status().isOk())
                .andDo(print(System.out))
                .andExpect(jsonPath("$.firstName").value("Laurent"));

                //.andExpect(jsonPath("$[0].firstName", is("Laurent")));
    }
}

提前感谢您的回答!
EDIT:构建数据库时使用的SQL脚本:

DROP TABLE IF EXISTS employees;
 
CREATE TABLE employees (
  id INT AUTO_INCREMENT  PRIMARY KEY,
  first_name VARCHAR(250) NOT NULL,
  last_name VARCHAR(250) NOT NULL,
  mail VARCHAR(250) NOT NULL,
  password VARCHAR(250) NOT NULL
)
 
INSERT INTO employees (first_name, last_name, mail, password) VALUES
  ('Laurent', 'GINA', 'laurentgina@mail.com', 'laurent'),
  ('Sophie', 'FONCEK', 'sophiefoncek@mail.com', 'sophie'),
  ('Agathe', 'FEELING', 'agathefeeling@mail.com', 'agathe');
unguejic

unguejic1#

代码似乎有几个问题。
首先,在EmployeeController类的getEmployee方法中,if条件检查employeeService返回的Optional是否为空,但如果为空,则代码返回null,这不是所需的行为。相反,您应该检查Optional是否存在,如果存在,则返回值,否则返回相应的响应,指示未找到该员工。

@GetMapping("/employee/{id}")
public Employee getEmployee(@PathVariable("id") final Long id) {
    Optional<Employee> emp = employeeService.getEmployee(id);

    if (emp.isPresent()) {
        Employee employe = emp.get();
        System.out.println(employe.getFirstName());
        return employe;
    } else {
        System.out.println("ABSENT");
        // return an appropriate response indicating that the employee was not found
        return null;
    }
}

同样的问题也适用于没有路径变量的getEmployee方法。

@GetMapping("/employee")
public Employee getEmployee() {
    Optional<Employee> emp = employeeService.getEmployee(1L);

    if (emp.isPresent()) {
        Employee employe = emp.get();
        System.out.println(employe.getFirstName());
        return employe;
    } else {
        System.out.println("ABSENT");
        // return an appropriate response indicating that the employee was not found
        return null;
    }
}

关于Junit测试类的问题,如果没有更多的信息,比如确切的错误消息或测试类的代码片段,很难确定问题所在。
总的来说,代码在处理找不到员工的情况时需要更加健壮,并且需要进一步调查测试类以确定问题的根本原因。

相关问题