mockito 预期值:用户的Mock,hashCode:1835841364实际:空

slsn1g29  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(97)

我为我的UserService类编写了一个模拟测试,但不明白为什么create方法的测试显示为橙子。我想弄清楚这是由于拼写错误的方法还是拼写错误的测试。这是我的命令类。

/**
 * A class that represents an order and contains the selected products and the customer.
 */

@Entity
@Table(name = "orders", schema = "public")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    //@JoinColumn
    private Product product;

    @ManyToMany
    private List<Product> products;

    @ManyToOne(fetch = FetchType.LAZY)
    //Multiple orders can belong to one customer. This means that a customer can place several orders.
    private User user;

    public Order() {
        //Default constructor
    }

    public Order(User user, Product product) {
        this.user = user;
        this.product = product;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

    public List<Product> getProducts() {
        return products;
    }
    public void setProducts(List<Product> products) {
        this.products = products;
    }
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

我的OrderService类:

/**
 * A class that implements the order process and includes functions to create orders, display the order history of a customer and confirm the order.
 */
@Service
public class OrderService {
    @Autowired
    OrderRepository or;

    public void save(Order order) {
        or.save(order);
    }
    public List<Order> listAll(){
        return (List<Order>) or.findAll();
    }

    public Order create(User user, Product product) {
        Order newOrder = new Order();
        newOrder.setUser(user);
        newOrder.setProduct(product);
        return or.save(newOrder);
    }

    public void delete(Long id) {
        Optional<Order> existingOrder= or.findById(id);
        if(existingOrder.isPresent()){
            or.deleteById(id);
        } else {
            throw new IllegalArgumentException("Order with ID " + id + " not found.");
        }
    }
}

Meine Klasse订单存储库:

@Repository
    public interface OrderRepository extends CrudRepository<Order, Long> {
        long countById(Long id); }

下面是显示为橙子的模拟测试:

public class OrderServiceTest {

    @InjectMocks
    private OrderService orderService;
    @InjectMocks
    private ProductService productService;

    @Mock
    private OrderRepository orderRepository;
    @Mock
    private ProductRepository productRepository;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testCreateOrder() {
        MockitoAnnotations.openMocks(this);

        Product product = new Product();
        product.setProductName("productName_0");
        product.setProductSalePrice(1290.78);

        User mockUser = Mockito.mock(User.class); // Create a mock User object

        Order mockOrder = new Order();

        when(orderRepository.save(any(Order.class))).thenReturn(mockOrder);

        Order createdOrder = orderService.create(mockUser, product);

        assertNotNull(createdOrder);
        assertEquals(mockUser, createdOrder.getUser());
        assertEquals(product, createdOrder.getProduct());

        verify(orderRepository, times(1)).save(any(Order.class));
    }

enter image description here我已经尝试在测试中进行更改。因为在数据库中,它被正确地标记为“用户”,更具体地说是“用户ID”,所以这对我来说更令人困惑。

xwbd5t1u

xwbd5t1u1#

让我们来分解一下:

Order mockOrder = new Order(); // this is not a Mockito mock

when(orderRepository.save(any(Order.class))).thenReturn(mockOrder);

Order createdOrder = orderService.create(mockUser, product);

// at this point: createdOrder == mockOrder (same reference)

使用无参数构造函数的Order类(new Order()):

public class Order {
    private Long id;
    private Product product;
    private List<Product> products;

    private User user;

    public Order() {
        // Parameterless constructor: all fields default-initialized
    }

    // ...
}

然后你的Assert:

assertEquals(mockUser, createdOrder.getUser());

记住:createdOrder == mockOrdermockOrder只是类的默认初始化示例,所以它的user字段仍然是null
如果你要求你的测试双精度型返回特定的值,你必须相应地设置它们。但我想知道你的测试是什么。你可能会完全搞砸你的服务实现,把错误的Order示例传递给你的仓库,等等。你的测试仍然会成功,因为唯一相关的行是return or.save(newOrder),并且该方法被存根为when(orderRepository.save(any(Order.class))).thenReturn(mockOrder),这意味着它将返回相同的mockOrder示例,对于除了null之外的任何输入。
你的测试不是测试任何有用的东西。它只是测试Mockito可以存根接口调用的返回值。
更有意义的测试可能是:

@Test
public void testCreateOrder() {
    Product product = new Product();
    product.setProductName("productName_0");
    product.setProductSalePrice(1290.78);

    User mockUser = Mockito.mock();

    orderService.create(mockUser, product);

    final ArgumentCaptor<Order> captor
            = ArgumentCaptor.forClass(Order.class);
    verify(orderRepository).save(captor.capture());

    final Order savedOrder = captor.getValue();
    assertEquals(mockUser, order.getUser());
    assertEquals(product, order.getProduct());
}

它验证repository.save是否已被调用,订单中的用户和产品设置是否正确。但是如果您正在测试数据库交互,我建议您编写一个集成测试,它实际上可以持久化您的实体。

相关问题