单元测试void控制器和服务方法

huangapple go评论59阅读模式
英文:

Unit testing void controller and service methods

问题

Controller方法:

@RequestMapping(method = RequestMethod.POST, value = "/products")
public void addProduct(@RequestBody Product product) {
    productService.addProduct(product);
}

Service方法:

public void addProduct(Product product) {
    productRepository.save(product);
}

Controller测试:

@Test
public void addProduct() {
    Product product = new Product();
    product.setId("001");
    product.setName("TV");
    product.setPrice(999.99);

    doNothing().when(productService).addProduct(product); // 这里是模拟调用 productService.addProduct() 方法
    productController.addProduct(product);

    // 在这里可以添加断言来验证期望的行为是否发生
}

Service测试:

@Test
public void addProduct() {
    Product product = new Product();
    product.setId("001");
    product.setName("TV");
    product.setPrice(999.99);

    when(productRepository.save(product)).thenReturn(product); // 这里是模拟调用 productRepository.save() 方法
    Product savedProduct = productService.addProduct(product);

    // 在这里可以添加断言来验证期望的行为是否发生
}

希望这些代码对你有所帮助。如果还有其他问题,请随时提问。

英文:

I have built a REST API that does basic CRUD operations on a product database and I am now unit testing all the methods within the controller and service layer. I have realised that methods such as addProduct, updateProduct or deleteProduct return void on both of the layers.

How do I go about mocking the repository when testing the service layer and mocking the service while testing controller layer for these methods?

Controller method:

@RequestMapping(method= RequestMethod.POST,value ="/products")
public void addProduct(@RequestBody Product product){
    productService.addProduct(product);
}

Service method:

public void addProduct(Product product){
    productRepository.save(product);
}

I have commented in the fields where I need help for the addProduct() methods.

Controller tests:

package com.product.controllers;

import com.product.entities.Product;
import com.product.services.ProductService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class ProductControllerTest {

@InjectMocks
ProductController productController;

@Mock
ProductService productService;

@Test
public void getHomePage(){
    String homePageText = "Welcome to the home page!";
    assertEquals(homePageText,productController.getHomePage());
}

@Test
public void getAllProducts(){
    
    Product product1 = new Product();
    product1.setId("001");
    product1.setName("TV");
    product1.setPrice(999.99);

    Product product2 = new Product();
    product2.setId("002");
    product2.setName("Mobile");
    product2.setPrice(300D);

    List<Product> listOfProducts = new ArrayList<>();
    listOfProducts.add(product1);
    listOfProducts.add(product2);

    when(productService.getAllProducts()).thenReturn(listOfProducts);
    assertEquals(listOfProducts,productController.getAllProducts());
}

@Test
public void getProductById(){
    
    Product product = new Product();
    product.setId("001");
    product.setName("TV");
    product.setPrice(999.99);

    when(productService.getProductById("001")).thenReturn(product);
    assertEquals(new ResponseEntity<Product> (product, HttpStatus.OK),productController.getProductById("001"));
}

@Test
public void addProduct() {
    
    Product product = new Product();
    product.setId("001");
    product.setName("TV");
    product.setPrice(999.99);

    // need help with this
}
}

Service tests:

package com.product.services;

import com.product.entities.Product;
import com.product.repositories.ProductRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class ProductServiceTest {

@InjectMocks
ProductService productService;

@Mock
ProductRepository productRepository;

@Test
public void getAllProducts() {

    Product product1 = new Product();
    product1.setId("001");
    product1.setName("TV");
    product1.setPrice(999.99);

    Product product2 = new Product();
    product2.setId("002");
    product2.setName("Mobile");
    product2.setPrice(300D);

    List<Product> listOfProducts = new ArrayList<>();
    listOfProducts.add(product1);
    listOfProducts.add(product2);

    when(productRepository.findAll()).thenReturn(listOfProducts);
    assertEquals(listOfProducts, productService.getAllProducts());
}

@Test
public void getProductById() {

    Product product = new Product();
    product.setId("001");
    product.setName("TV");
    product.setPrice(999.99);

    when(productRepository.findById("001")).thenReturn(java.util.Optional.of(product));
    assertEquals(product, productService.getProductById("001"));


}

@Test
public void addProduct() {

    Product product = new Product();
    product.setId("001");
    product.setName("TV");
    product.setPrice(999.99);

    // need help with this
}
}

答案1

得分: 1

这段代码非常简单,所以我不确定你是否需要对其进行单元测试。但如果你想要的话,你可以利用Mockito的模拟对象的verify方法。例如,在测试addProduct时:

@InjectMocks
ProductService productService;

@Mock
ProductRepository productRepository;

// ...

@Test
public void testAddProduct() { 
   Product dummyProduct = new Product();

   productService.addProduct(dummyProduct);

   // eq()来自于Mockito的匹配器包
   Mockito.verify(productRepository, Mockito.times(1)).save(eq(dummyProduct))
}

这段代码验证了在模拟的仓库上是否正确调用了一次save方法,并且传入的参数是dummyProduct

你可能还想了解一下Mockito的“参数捕获器”功能。

英文:

This code is quite simple so I'm not sure you need to unit test it. But if you want to, you can make use of your Mockito's mocks' verify method. For example when testing addProduct :

@InjectMocks
ProductService productService;

@Mock
ProductRepository productRepository;

// ...

@Test
public void testAddProduct() { 
   Product dummyProduct = new Product();

   productService.addProduct(dummyProduct);

   // eq() is from the Mockito matchers package
   Mockito.verify(productRepository, Mockito.times(1)).save(eq(dummyProduct))
}

This verifies that save was called on time on the mocked repository with an argument of dummyProduct.

You also may want to check out Mockito "argument captors".

huangapple
  • 本文由 发表于 2020年9月7日 17:25:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/63774801.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定