当我 运行 spring 启动测试用例时出现错误,我无法自行解决

When I run spring boot test cases I got error I could not resolve on my own

我正在为我的控制器创建测试用例

package com.bank.controller;

import static org.assertj.core.api.Assertions.assertThat;

import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.http.MediaType;
import com.bank.model.Account;
import com.bank.model.Customer;
import com.bank.service.AccountService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;


@RunWith(SpringRunner.class)
@WebMvcTest(value=AccountController.class)
class AccountControllerTest{

    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private AccountService accountService;
    
    
    @Test
    public void testcreateAccount() throws Exception{
         Customer customer=new Customer();
         customer.setCustomerId(1);
         customer.setCustomerName("Manasa");
         
        Account mockAccount=new Account();
        mockAccount.setAccountNumber(456);
        mockAccount.setBalance(2000.0);
        mockAccount.setAccountType("savings");
        mockAccount.setCustomer(customer);
        
        
        String inputInJson=this.mapToJson(mockAccount);
        String URI="/account";
        Mockito.when(accountService.accountCreate(Mockito.any(Account.class))).thenReturn(mockAccount);
        RequestBuilder requestBuilder=MockMvcRequestBuilders
                .post(URI)
                .accept(MediaType.APPLICATION_JSON).content(inputInJson)
                .contentType(MediaType.APPLICATION_JSON);
        MvcResult result=mockMvc.perform(requestBuilder).andReturn();
        MockHttpServletResponse response=result.getResponse();
         String outputInJson=response.getContentAsString();
         assertThat(outputInJson).isEqualTo(outputInJson);
         assertEquals(HttpStatus.OK.value(),response.getStatus());
        
    }

    
    @Test
    public void testaccountList() throws Exception{
        
         Customer customer1=new Customer();
         customer1.setCustomerId(1);
         customer1.setCustomerName("Manasa");
         
        
        Account mockAccount1=new Account();
        mockAccount1.setAccountNumber(456);
        mockAccount1.setAccountType("savings");
        mockAccount1.setBalance(2000.0);
        mockAccount1.setCustomer(customer1);
        
         Customer customer2=new Customer();
         customer2.setCustomerId(2);
         customer2.setCustomerName("Madhu");
        
        Account mockAccount2=new Account();
        mockAccount2.setAccountNumber(789);
        mockAccount2.setAccountType("savings");
        mockAccount2.setBalance(6000.0);
        mockAccount2.setCustomer(customer2);
        
         Customer customer3=new Customer();
         customer3.setCustomerId(3);
         customer3.setCustomerName("Lalasa");
         
        
        Account mockAccount3=new Account();
        mockAccount3.setAccountNumber(123);
        mockAccount3.setAccountType("savings");
        mockAccount3.setBalance(50000.0);
        mockAccount3.setCustomer((Customer)Arrays.asList(3,"Lalasa"));
        
        List<Account> accountList=new ArrayList<>();
        accountList.add(mockAccount1);
        accountList.add(mockAccount2);
        accountList.add(mockAccount3);
        
        Mockito.when(accountService.allAccounts()).thenReturn(accountList);
        
        String URI="/account/aclist";
        RequestBuilder requestBuilder=MockMvcRequestBuilders.get(
                URI).accept(MediaType.APPLICATION_JSON);
        
        MvcResult result=mockMvc.perform(requestBuilder).andReturn();
        String expectedJson=this.mapToJson(accountList);
        String outputInJson=result.getResponse().getContentAsString();
        assertThat(outputInJson).isEqualTo(expectedJson);   
        
    }
    
    @Test
    public void testbyAccountType() throws Exception{
        
         Customer customer=new Customer();
         customer.setCustomerId(1);
         customer.setCustomerName("Manasa");
         
        
        Account mockAccount=new Account();
        mockAccount.setAccountNumber(456);
        mockAccount.setAccountType("savings");
        mockAccount.setBalance(2000.0);
        mockAccount.setCustomer(customer);
        
        String expectedJson=this.mapToJson(mockAccount);
        Mockito.when(accountService.accountByType(Mockito.anyString())).thenReturn((List<Account>) mockAccount);
        
        String URI="/account//byType/savings";
        RequestBuilder requestBuilder=MockMvcRequestBuilders.get(
                URI).accept(MediaType.APPLICATION_JSON);
        
        MvcResult result=mockMvc.perform(requestBuilder).andReturn();
        String outputInJson=result.getResponse().getContentAsString();
        assertThat(outputInJson).isEqualTo(expectedJson);       
        
    }
    
    
    private String mapToJson(Object object) throws JsonProcessingException{
        
        ObjectMapper objectMapper=new ObjectMapper();
        return objectMapper.writeValueAsString(object);     
            
    }
}

我的控制器class是

package com.bank.controller;

import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.bank.model.Account;
import com.bank.service.AccountService;
import com.bank.Exception.ResourceNotFoundException;

@RestController
@RequestMapping("/account")
public class AccountController {

    @Autowired
    AccountService accountService;
    
    @PostMapping
    public ResponseEntity<?> createAccount(@RequestBody Account account) throws ResourceNotFoundException{
        Account acc=accountService.accountCreate(account);
        if(acc!=null) {
            return new ResponseEntity<>(acc,HttpStatus.CREATED);
        }else {
        throw new ResourceNotFoundException("Account is not Created!!");
        }   
    }
    
    @GetMapping("/aclist")
    public ResponseEntity<?> accountList() throws ResourceNotFoundException{
        
        List<Account> accountList=accountService.allAccounts();
        if(!(accountList.isEmpty())) {
            return new ResponseEntity<>(accountList,HttpStatus.OK);
        }else {
            throw new ResourceNotFoundException("accounts not found");
        }
        
    }
    
    @GetMapping("/byType/{accountType}")
    public ResponseEntity<?> byAccountType(@PathVariable String accountType) throws ResourceNotFoundException{
        List<Account> account =accountService.accountByType(accountType);
        if(account.isEmpty()) {
            throw new ResourceNotFoundException(accountType+""+"Type of account does not exist!!");
        }else {
            return new ResponseEntity<>(account,HttpStatus.OK);
        }
    }
    
    @GetMapping("/{accountNumber}")
    public ResponseEntity<?> getAccountById(@PathVariable("accountNumber") int accountNumber) throws ResourceNotFoundException{
        Account acc=accountService.findAccountById(accountNumber);
        if(acc!=null) {
            return new ResponseEntity<>(acc,HttpStatus.OK);
        }else {
            throw new ResourceNotFoundException("account [accountNumber="+accountNumber+"] can't be found");
        }
    }

    @PutMapping("/{from}/{to}/{amount}")
    public ResponseEntity<?> transferFunds(@PathVariable("from") int from,@PathVariable("to") int to,@PathVariable("amount") double amount) throws ResourceNotFoundException{
        return accountService.transferFunds(from, to, amount);  
    }
    
    @DeleteMapping("/{accountNumber}")
    public ResponseEntity<?> deleteAccById(@PathVariable ("accountNumber") int accountNumber) throws ResourceNotFoundException{
        String x=accountService.deleteById(accountNumber);
        if(x.equalsIgnoreCase("deleted")){
            return new ResponseEntity<>("deleted successfully",HttpStatus.OK);
        }else {
            throw new ResourceNotFoundException("Account [accountNumber="+accountNumber+"] can't be found");
        }
    }
    
    @GetMapping("/balance/{accountNumber}")
    public ResponseEntity<?> getBalanceById(@PathVariable ("accountNumber") int accountNumber) throws ResourceNotFoundException{
        String balance=accountService.getBalanceById(accountNumber);
        
        if(balance.equalsIgnoreCase("Invalid accountNumber")) {
            throw new ResourceNotFoundException("Account [accountNumber="+accountNumber+"] can't be found");
            
        }else {
            return new ResponseEntity<>(balance,HttpStatus.OK);
        }
    }
    
    @DeleteMapping("/deleteAll")
    public ResponseEntity<?> deleteAllAccounts(){
        return new ResponseEntity<>(accountService.deleteAllAccounts(),HttpStatus.OK);
    }   

    @PutMapping("/update/{accountNumber}")
    public ResponseEntity<?> UpdateAccount(@PathVariable ("accountNumber") int accountNumber,@RequestBody Account account) throws ResourceNotFoundException{
        Account acc=accountService.updateAccount(accountNumber, account);
        if(acc!=null) {
            return new ResponseEntity<>(acc,HttpStatus.OK);
        }else {
            throw new ResourceNotFoundException("invalid accountNumber and account");
        }
    }
    
    @PutMapping("/deposite/{amount}/{accountNumber}")
    public ResponseEntity<?> deposite(@PathVariable("amount") double amount,@PathVariable("accountNumber") int accountNumber) throws ResourceNotFoundException{
        
        
            return accountService.deposite(amount,accountNumber);
    }
    @PutMapping("/withdraw/{amount}/{accountNumber}")   
    public ResponseEntity<?> withDraw(@PathVariable("amount") double amount,@PathVariable("accountNumber") int accountNumber) throws ResourceNotFoundException{
        return accountService.withdraw(amount,accountNumber);
    }
}
    

我的模型class是(与客户有多对一关系class)

    package com.bank.model;
    
    import javax.persistence.CascadeType;
    
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.Proxy;
    
    @Entity
    @Table(name="Account")
    @Proxy(lazy = false)
    public class Account {
    
        @Id
        int accountNumber;
        @Column(name="balance")
        Double balance;
        @Column(name="accountType")
        String accountType;
        
        @ManyToOne( targetEntity=Customer.class,cascade = CascadeType.ALL)
        @JoinColumn(name="ca_fk",referencedColumnName = "customerId")
        Customer customer;
    
        public Account() {
            super();
            
        }
    
        public Account(int accountNumber, Double balance, String accountType, Customer customer) {
            super();
            this.accountNumber = accountNumber;
            this.balance = balance;
            this.accountType = accountType;
            this.customer = customer;
        }
    
        @Override
        public String toString() {
            return "Account [accountNumber=" + accountNumber + ", balance=" + balance + ", accountType=" + accountType
                    + ", customer=" + customer + "]";
        }
    
        public Integer getAccountNumber() {
            return accountNumber;
        }
    
        public void setAccountNumber(int accountNumber) {
            this.accountNumber = accountNumber;
        }
    
        public Double getBalance() {
            return balance;
        }
    
        public void setBalance(Double balance) {
            this.balance = balance;
        }
    
        public String getAccountType() {
            return accountType;
        }
    
        public void setAccountType(String accountType) {
            this.accountType = accountType;
        }
    
        public Customer getCustomer() {
            return customer;
        }
    
        public void setCustomer(Customer customer) {
            this.customer = customer;
        }
        
        
    }
    

顾客class

    package com.bank.model;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.Proxy;
    
    @Entity
    @Table(name="Customer")
    @Proxy(lazy = false)
    public class Customer {
    
        @Id
        Integer customerId;
        @Column(name="customerName")
        String customerName;
        
        public Customer() {
            super();
            
        }
    
        public Customer(int customerId, String customerName) {
            super();
            this.customerId = customerId;
            this.customerName = customerName;
        }
    
        @Override
        public String toString() {
            return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]";
        }
    
        public int getCustomerId() {
            return customerId;
        }
    
        public void setCustomerId(int customerId) {
            this.customerId = customerId;
        }
    
        public String getCustomerName() {
            return customerName;
        }
    
        public void setCustomerName(String customerName) {
            this.customerName = customerName;
        }
        
    }

我收到以下错误

    MockHttpServletRequest:
          HTTP Method = POST
          Request URI = /account
           Parameters = {}
              Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"114"]
                 Body = {"accountNumber":456,"balance":2000.0,"accountType":"savings","customer":{"customerId":1,"customerName":"Manasa"}}
        Session Attrs = {}
    
    Handler:
                 Type = com.bank.controller.AccountController
               Method = com.bank.controller.AccountController#createAccount(Account)
    
    Async:
        Async started = false
         Async result = null
    
    Resolved Exception:
                 Type = null
    
    ModelAndView:
            View name = null
                 View = null
                Model = null
    
    FlashMap:
           Attributes = null
    
    MockHttpServletResponse:
               Status = 201
        Error message = null
              Headers = [Content-Type:"application/json"]
         Content type = application/json
                 Body = {"accountNumber":456,"balance":2000.0,"accountType":"savings","customer":{"customerId":1,"customerName":"Manasa"}}
        Forwarded URL = null
       Redirected URL = null
              Cookies = []
    2022-03-20 02:11:12.422  WARN 12996 --- [           main] o.s.test.context.TestContextManager      : Caught exception while invoking 'afterTestMethod' callback on TestExecutionListener [org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@485e36bc] for test method [public void com.bank.controller.AccountControllerTest.testbyAccountType() throws java.lang.Exception] and test instance [com.bank.controller.AccountControllerTest@153cfd86]
    
    org.mockito.exceptions.misusing.UnfinishedStubbingException: 
    Unfinished stubbing detected here:
    -> at com.bank.controller.AccountControllerTest.testbyAccountType(AccountControllerTest.java:139)
    
    E.g. thenReturn() may be missing.
    Examples of correct stubbing:
        when(mock.isOk()).thenReturn(true);
        when(mock.isOk()).thenThrow(exception);
        doThrow(exception).when(mock).someVoidMethod();
    Hints:
     1. missing thenReturn()
     2. you are trying to stub a final method, which is not supported
     3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed
    
        at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:83) ~[spring-boot-test-2.6.4.jar:2.6.4]
        at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:70) ~[spring-boot-test-2.6.4.jar:2.6.4]
        at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.afterTestMethod(ResetMocksTestExecutionListener.java:64) ~[spring-boot-test-2.6.4.jar:2.6.4]
        at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:445) ~[spring-test-5.3.16.jar:5.3.16]
        at org.springframework.test.context.junit.jupiter.SpringExtension.afterEach(SpringExtension.java:206) ~[spring-test-5.3.16.jar:5.3.16]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks(TestMethodTestDescriptor.java:257) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:273) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.8.2.jar:1.8.2]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:273) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:272) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:256) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:141) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66) ~[junit-jupiter-engine-5.8.2.jar:5.8.2]
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:151) ~[junit-platform-engine-1.8.2.jar:1.8.2]
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.8.2.jar:1.8.2]
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively(NodeTestTask.java:141) ~[junit-platform-engine-1.8.2.jar:1.8.2]
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.8.2.jar:1.8.2]

我的pom.xml是

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.bank</groupId>
    <artifactId>capstoneBankProject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>capstoneBankProject</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
        <junit.version>4.13.1</junit.version>
    </properties>
    <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
<!-- exclude junit 4 -->
 
   
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
  </exclusions>
</dependency>
<!-- Junit 5 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

我的项目结构

您正在将 mockAccount 强制转换为一个列表,而实际上它并不是一个列表,这可能就是模拟失败的原因。