Java spring 测试表单端点

Java spring test form endpoint

我想创建测试来测试我的插入表单端点。问题是当我 运行 测试给我这个错误 - java.lang.NullPointerException at com.zetcode.integrationTest.Test2.testRegistration(Test2.java:52)

这是我的端点

Controller
public class CreateAccountUserController {

    @RequestMapping(value = "/CreateUserAccount", method = RequestMethod.POST)

    public String createAccount(
            @RequestParam(value = "fullName", required = false) String fullName,
            @RequestParam(value = "email", required = false) String email,
            @RequestParam(value = "username", required = false) String username,
            @RequestParam(value = "password", required = false) String password,
            Model model,
            HttpServletRequest request
    ) throws SQLException, NamingException {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        dataSource.setUsername("mssqllogin");
        dataSource.setPassword("mssqllogin$");
        dataSource.setUrl("jdbc:sqlserver://localhost\SQLEXPRESS:1433;databaseName=AdminToolWeb");
        
        try {
            EncryptPasswords td = new EncryptPasswords();
            emp.setPassword(td.encrypt(emp.getPassword()));
            Connection connection2 = dataSource.getConnection();
            PreparedStatement st = connection2.prepareStatement(
                    "INSERT INTO Accounts (FirstName_DB, Username_DB, Password_DB, Email_DB, Type_DB) VALUES (?,?,?,?,?)");
            st.setString(1, emp.getFirstName());
            st.setString(2, emp.getUsername());
            st.setString(3, emp.getPassword());
            st.setString(4, emp.getEmail());
            st.setString(5, "2");
            st.executeQuery();
            st.close();
            connection2.close();

        } catch (Exception e) {

        }
    } 
}

这是我的 html 表格

<form class="form" method="post" th:action="@{/CreateUserAccount}">
    <input type="text" class="fullname" th:name="fullName" th:value="${fullName}"  placeholder="Имена" required>
    <input type="email" class="email" th:name="email" th:value="${email}" placeholder="Имейл" required>
    <input type="text" class="username" th:name="username" th:value="${username}"  placeholder="Потребителско име" required>
    <input type="password" class="password" th:name="password" th:value="${password}"  placeholder="Парола" required>
    <button class="buttonLogin" type="submit">Регистрирай</button>
</form>

这是我的测试 - 问题是当我设置 url 时。我不太确定这是正确的格式

package com.zetcode.integrationTest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zetcode.model.Employee;
import com.zetcode.model.EncryptPasswords;
import com.zetcode.model.FileLogWrite;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.*;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.junit.Test;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;
import static org.springframework.mock.http.server.reactive.MockServerHttpRequest.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class Test2 {
    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired private MockMvc mockMvc;
    @Autowired private ObjectMapper mapper;

    @BeforeEach
    public void setup() throws Exception {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
    }

    @Test
    public void testRegistration() throws Exception {

        String name = "Ivan Memed Memed";
        String email = "test@abv.bg";
        String username = "IntegrationTest";
        String password = "12345678";



        this.mockMvc.perform(MockMvcRequestBuilders.post("localhost:8080/CreateUserAccount")
                .param("fullName", name)
                .param("email", email)
                .param("username", username)
                .param("password", password));

        this.mockMvc.perform(MockMvcRequestBuilders.post("localhost:8080/CreateUserAccount")
                .param("fullName", name)
                .param("email", email)
                .param("username", username)
                .param("password", password)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());




        EncryptPasswords td = new EncryptPasswords();
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        dataSource.setUsername("mssqllogin");
        dataSource.setPassword("mssqllogin$");
        dataSource.setUrl("jdbc:sqlserver://localhost\SQLEXPRESS:1433;databaseName=AdminToolWeb");
        Connection connection = dataSource.getConnection();
        PreparedStatement st2 = connection.prepareStatement(
                "SELECT * FROM Accounts where FirstName_DB = ? and Email_DB = ? and Username_DB = ? and Email_DB = ? and Type_DB = 2");
        st2.setString(1, name);
        st2.setString(2, email);
        st2.setString(3, username);
        st2.setString(4, td.encrypt(password));
        ResultSet resultSet = st2.executeQuery();
        if (resultSet.next()) {
            assertTrue("This will succeed.", true);
        } else {
            assertFalse("This will fail!", false);
        }

    }
}

这是堆栈跟踪

java.lang.NullPointerException
    at com.zetcode.integrationTest.Test2.testRegistration(Test2.java:53)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access0(ParentRunner.java:66)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)


使用默认的 @SpringBootTest 来处理依赖项的注入和 @AutoConfigureMockMvc 的自动 mockMvc 配置对我来说非常完美

这是我使用的测试文件的精简版:

package com.example.demo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

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

@SpringBootTest
@AutoConfigureMockMvc
@RunWith(SpringRunner.class)
public class CreateAccountUserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void createAccountTest() throws Exception {
        String name = "Ivan Memed Memed";
        String email = "test@abv.bg";
        String username = "IntegrationTest";
        String password = "12345678";

        this.mockMvc.perform(MockMvcRequestBuilders.post("/CreateUserAccount")
                .param("fullName", name)
                .param("email", email)
                .param("username", username)
                .param("password", password));

        this.mockMvc.perform(MockMvcRequestBuilders.post("/CreateUserAccount")
                .param("fullName", name)
                .param("email", email)
                .param("username", username)
                .param("password", password)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}

你有很多不同的测试依赖项,它们带来了冲突的版本和做同样事情的包。我建议只使用 spring 引导启动程序测试包:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

并删除所有其他测试包:

<dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>5.7.0</version>
      <scope>test</scope>
   </dependency>
   <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.7.0</version>
   </dependency>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.3.3</version>
      <scope>test</scope>
   </dependency>
   <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-test</artifactId>
      <version>2.3.4.RELEASE</version>
   </dependency>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.2.RELEASE</version>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-test-autoconfigure</artifactId>
      <version>2.3.4.RELEASE</version>
   </dependency>