首页 > 解决方案 > 如果直接命中端点而不是映射器,如何回滚?

问题描述

我的目标是在控制器测试后回滚更改(在数据库上)。

我做了什么:

  1. 如果我直接测试 AccountMapper(而不是点击 POST /account/{from_account_number}/transfer),测试将回滚。

预期结果:

  1. 控制器的测试将在每次测试后回滚更改。

实际结果:

  1. 控制器的测试没有回滚更改。

对于完整的存储库:https ://github.com/kidfrom/learn-java/tree/main/etc/bankaccount

AccountController.java

package codeassignment.bankaccount.controller;

import codeassignment.bankaccount.mapper.AccountMapper;
import codeassignment.bankaccount.mapper.CustomerMapper;
import codeassignment.bankaccount.model.AccountModel;
import codeassignment.bankaccount.model.GetCurrentBalanceModel;
import codeassignment.bankaccount.model.PostTransferModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;

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

  @Autowired
  AccountMapper accountMapper;

  @PostMapping("/{from_account_number}/transfer")
  public ResponseEntity<Object> postTransfer(@PathVariable("from_account_number") @Pattern(regexp = "[0-9]+", message = "uri /account/{from_account_number}/transfer, {from_account_number} must only contain number") String fromAccountNumber, @Valid @RequestBody PostTransferModel requestBody) {
    if (fromAccountNumber.equals(requestBody.getTo_account_number())) {
      return ResponseEntity.badRequest().body("from_account_number must not be equal to to_account_number");
    } else {
      if (!accountMapper.exists(requestBody.getTo_account_number())) {
        return ResponseEntity.notFound().build();
      } else {
        BigDecimal currentBalance = accountMapper.getBalance(fromAccountNumber);

        if (currentBalance == null) {
          return ResponseEntity.notFound().build();
        } else if (currentBalance.compareTo(requestBody.getAmount()) < 0) {
          return ResponseEntity.status(402).body("Insufficient balance");
        } else {

          if (accountMapper.updateBalance(currentBalance.subtract(requestBody.getAmount()), fromAccountNumber) != 1) {
            return ResponseEntity.status(500).body("Update failed");
          } else {
            if (accountMapper.addBalance(requestBody) != 1) {
              return ResponseEntity.status(500).body("Update failed");
            } else {
              return new ResponseEntity<>("", HttpStatus.CREATED);
            }
          }
        }
      }
    }
  }
}

AccountMapper.java

package codeassignment.bankaccount.mapper;

import codeassignment.bankaccount.model.AccountModel;
import codeassignment.bankaccount.model.PostTransferModel;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.math.BigDecimal;

@Mapper
public interface AccountMapper {

  @Select("SELECT customer_number, balance FROM account WHERE account_number=#{accountNumber}")
  AccountModel getCustomerNumberAndBalance(String accountNumber);

  @Select("SELECT balance FROM account WHERE account_number=#{accountNumber}")
  BigDecimal getBalance(String accountNumber);

  @Select("SELECT EXISTS(SELECT 1 FROM account WHERE account_number=#{accountNumber})")
  boolean exists(String accountNumber);

  @Update("UPDATE account SET balance=#{balance} WHERE account_number=#{accountNumber}")
  int updateBalance(BigDecimal balance, String accountNumber);

  @Update("UPDATE account SET balance=balance+#{amount} WHERE account_number=#{to_account_number}")
  int addBalance(PostTransferModel requestBody);
}

AccountControllerTest.java

package codeassignment.bankaccount.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.boot.test.autoconfigure.AutoConfigureMybatis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import java.util.HashMap;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest
@AutoConfigureMybatis
class AccountControllerTest {

  @Autowired
  private MockMvc mockMvc;

  @Test
  void postTransferCreated() throws Exception {
    HashMap<String, Object> requestBody = new HashMap<>();
    requestBody.put("to_account_number", "555002");
    requestBody.put("amount", 10000);
    mockMvc.perform(
            post("/account/555001/transfer")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(new ObjectMapper().writeValueAsString(requestBody)))
            .andExpect(status().isCreated());
  }
}

标签: springspring-bootmybatisspring-boot-test

解决方案


推荐阅读