Spring 使用 mockito 的 MVC 模拟未发生在服务层
Spring MVC mocking using mockito not happening on service layer
这是我的控制器:
@RestController
public class LoanController {
@Autowired
private LoanService loanService;
@GetMapping("/loans/{id}")
public Loan getLoan(@PathVariable Long id) {
return loanService.getLoan(id);
}
@PostMapping("/loans")
public ResponseEntity <String> addLoan(@RequestBody Loan loan) {
System.out.println(" Test 2 >> " + loanService.isLoanProcessed(loan));
if(loanService.isLoanProcessed(loan)) {
return ResponseEntity.status(HttpStatus.CREATED).build(); //return http 201 return code
}
return ResponseEntity.status(HttpStatus.CONFLICT).build(); // return http 409 return code
}
}
服务:
@Service
public class LoanService {
@Autowired
private LoanRepository loanRepo;
public boolean isLoanProcessed(Loan loan) {
// Validate the Loan
if(isValid(loan)) {
// Get the Loan Fee
Double loanFees = getLoanFees(loan.getLoanType().trim());
// Get the total Loan Interest
Double totLoanInterest = calcLoanTotalInterest(loan.getLoanAmt(),loan.getRate(),loan.getLoanTerm());
// Get the APR
Double apr = getAPR(totLoanInterest,loanFees,loan.getLoanAmt(),loan.getLoanTerm());
// Set calculate APR to Loan model
loan.setApr(apr);
// Add the loan to db
this.addLoan(loan);
return true;
} else {
// If the Loan is not valid throw custom exception
// Still need to be implemented
return false;
}
}
这是测试类:
@SpringBootTest
@AutoConfigureMockMvc
public class LoanControllerIntegrationTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private LoanService mockLoanService;
private AutoCloseable closeable;
@InjectMocks
LoanController loanController;
private Loan loan;
private SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
@BeforeEach
public void init() throws Exception {
closeable = MockitoAnnotations.openMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(loanController).build();
}
@Test
@DisplayName("POST /loans")
final void addLoanIdTest() throws Exception {
loan.setApr(Double.valueOf(5.15));
loan.setLoanStatus("A");
when(mockLoanService.isLoanProcessed(loan)).thenReturn(true);
System.out.println(" Test 1 >> " + mockLoanService.isLoanProcessed(loan)); // printing true
mockMvc.perform(post("/loans")
.contentType(MediaType.APPLICATION_JSON)
.content(convertObjToJsonString(loan)))
.andExpect(status().isOk());
}
这是我的问题:
在测试中,当我在 mockLoanService.isLoanProcessed(loan)
值上打印时模拟正确发生,这是正确的,但在控制器中,post 方法修改模拟数据没有选择,当我打印显示为 false
,使用模拟数据未对控制器 if(loanService.isLoanProcessed(loan))
进行条件检查。请在我出错的地方提供您的意见。
在您之前的方法中,尝试添加:
MockitoAnnotations.initMocks(this);
它不起作用,因为您将 mock 绑定到在 LoanControllerIntegrationTests
class 中创建的特定 Loan
对象。在控制器中创建的对象不是同一个对象。
简单示例:
要解决您的问题,请使用any()
运算符:
when(mockLoanService.isLoanProcessed(any(Loan.class))).thenReturn(true);
您可以从以下导入语句中获取:
import static org.mockito.ArgumentMatchers.any;
这是我的控制器:
@RestController
public class LoanController {
@Autowired
private LoanService loanService;
@GetMapping("/loans/{id}")
public Loan getLoan(@PathVariable Long id) {
return loanService.getLoan(id);
}
@PostMapping("/loans")
public ResponseEntity <String> addLoan(@RequestBody Loan loan) {
System.out.println(" Test 2 >> " + loanService.isLoanProcessed(loan));
if(loanService.isLoanProcessed(loan)) {
return ResponseEntity.status(HttpStatus.CREATED).build(); //return http 201 return code
}
return ResponseEntity.status(HttpStatus.CONFLICT).build(); // return http 409 return code
}
}
服务:
@Service
public class LoanService {
@Autowired
private LoanRepository loanRepo;
public boolean isLoanProcessed(Loan loan) {
// Validate the Loan
if(isValid(loan)) {
// Get the Loan Fee
Double loanFees = getLoanFees(loan.getLoanType().trim());
// Get the total Loan Interest
Double totLoanInterest = calcLoanTotalInterest(loan.getLoanAmt(),loan.getRate(),loan.getLoanTerm());
// Get the APR
Double apr = getAPR(totLoanInterest,loanFees,loan.getLoanAmt(),loan.getLoanTerm());
// Set calculate APR to Loan model
loan.setApr(apr);
// Add the loan to db
this.addLoan(loan);
return true;
} else {
// If the Loan is not valid throw custom exception
// Still need to be implemented
return false;
}
}
这是测试类:
@SpringBootTest
@AutoConfigureMockMvc
public class LoanControllerIntegrationTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private LoanService mockLoanService;
private AutoCloseable closeable;
@InjectMocks
LoanController loanController;
private Loan loan;
private SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
@BeforeEach
public void init() throws Exception {
closeable = MockitoAnnotations.openMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(loanController).build();
}
@Test
@DisplayName("POST /loans")
final void addLoanIdTest() throws Exception {
loan.setApr(Double.valueOf(5.15));
loan.setLoanStatus("A");
when(mockLoanService.isLoanProcessed(loan)).thenReturn(true);
System.out.println(" Test 1 >> " + mockLoanService.isLoanProcessed(loan)); // printing true
mockMvc.perform(post("/loans")
.contentType(MediaType.APPLICATION_JSON)
.content(convertObjToJsonString(loan)))
.andExpect(status().isOk());
}
这是我的问题:
在测试中,当我在 mockLoanService.isLoanProcessed(loan)
值上打印时模拟正确发生,这是正确的,但在控制器中,post 方法修改模拟数据没有选择,当我打印显示为 false
,使用模拟数据未对控制器 if(loanService.isLoanProcessed(loan))
进行条件检查。请在我出错的地方提供您的意见。
在您之前的方法中,尝试添加:
MockitoAnnotations.initMocks(this);
它不起作用,因为您将 mock 绑定到在 LoanControllerIntegrationTests
class 中创建的特定 Loan
对象。在控制器中创建的对象不是同一个对象。
简单示例:
要解决您的问题,请使用any()
运算符:
when(mockLoanService.isLoanProcessed(any(Loan.class))).thenReturn(true);
您可以从以下导入语句中获取:
import static org.mockito.ArgumentMatchers.any;