459 lines
15 KiB
C++
459 lines
15 KiB
C++
#include <gtest/gtest.h>
|
||
#include <gmock/gmock.h>
|
||
#include <memory>
|
||
#include <map>
|
||
#include <vector>
|
||
#include <string>
|
||
|
||
// 假设的模型类和服务类定义(用于测试)
|
||
struct Product {
|
||
long id;
|
||
std::string name;
|
||
double price;
|
||
};
|
||
|
||
struct CartItem {
|
||
long id;
|
||
long productId;
|
||
int quantity;
|
||
double totalPrice;
|
||
};
|
||
|
||
struct Order {
|
||
long id;
|
||
long userId;
|
||
std::string address;
|
||
std::vector<CartItem> items;
|
||
std::string status;
|
||
};
|
||
|
||
struct Refund {
|
||
long id;
|
||
long orderId;
|
||
std::string reason;
|
||
std::string status;
|
||
};
|
||
|
||
// Mock BusinessService
|
||
class MockBusinessService {
|
||
public:
|
||
MOCK_METHOD(std::vector<Product>, getProductsByCategory, (const std::string& category), (const));
|
||
MOCK_METHOD(Product, getProductById, (long id), (const));
|
||
MOCK_METHOD(std::vector<CartItem>, getUserCart, (long userId), (const));
|
||
MOCK_METHOD(CartItem, addToCart, (long userId, long productId, int quantity), (const));
|
||
MOCK_METHOD(bool, removeCartItem, (long userId, long itemId), (const));
|
||
MOCK_METHOD(Order, createOrderFromCart, (long userId, const std::string& address), (const));
|
||
MOCK_METHOD(Order, createOrderDirect, (long userId, long productId, int quantity, const std::string& address), (const));
|
||
MOCK_METHOD(std::vector<Order>, getUserOrders, (long userId), (const));
|
||
MOCK_METHOD(Order, getOrderById, (long userId, long id), (const));
|
||
MOCK_METHOD(Order, cancelOrder, (long userId, long id), (const));
|
||
MOCK_METHOD(Refund, applyRefund, (long userId, long orderId, const std::string& reason), (const));
|
||
MOCK_METHOD(std::vector<Refund>, getUserRefunds, (long userId), (const));
|
||
};
|
||
|
||
// 模拟 ResponseEntity 模板
|
||
template<typename T>
|
||
struct ResponseEntity {
|
||
T body;
|
||
int statusCode;
|
||
|
||
static ResponseEntity<T> ok(const T& data) {
|
||
ResponseEntity<T> res;
|
||
res.body = data;
|
||
res.statusCode = 200;
|
||
return res;
|
||
}
|
||
|
||
static ResponseEntity<T> created(const T& data) {
|
||
ResponseEntity<T> res;
|
||
res.body = data;
|
||
res.statusCode = 201;
|
||
return res;
|
||
}
|
||
|
||
static ResponseEntity<T> notFound() {
|
||
ResponseEntity<T> res;
|
||
res.statusCode = 404;
|
||
return res;
|
||
}
|
||
};
|
||
|
||
// 被测类:BusinessController
|
||
class BusinessController {
|
||
private:
|
||
MockBusinessService& businessService;
|
||
static constexpr long CURRENT_USER_ID = 1L;
|
||
|
||
public:
|
||
BusinessController(MockBusinessService& service) : businessService(service) {}
|
||
|
||
// ==================== 商品 ====================
|
||
ResponseEntity<Product> getProductById(long id) {
|
||
return ResponseEntity<Product>::ok(businessService.getProductById(id));
|
||
}
|
||
|
||
// ==================== 购物车 ====================
|
||
ResponseEntity<CartItem> addToCart(const std::map<std::string, std::any>& request) {
|
||
long productId = std::any_cast<long>(request.at("productId"));
|
||
int quantity = std::any_cast<int>(request.at("quantity"));
|
||
CartItem item = businessService.addToCart(CURRENT_USER_ID, productId, quantity);
|
||
return ResponseEntity<CartItem>::created(item);
|
||
}
|
||
|
||
// ==================== 订单 ====================
|
||
ResponseEntity<Order> createOrder(const std::map<std::string, std::string>& request) {
|
||
std::string address = request.count("address") ? request.at("address") : "默认收货地址";
|
||
Order order = businessService.createOrderFromCart(CURRENT_USER_ID, address);
|
||
return ResponseEntity<Order>::created(order);
|
||
}
|
||
|
||
ResponseEntity<Order> buyDirect(const std::map<std::string, std::any>& request) {
|
||
long productId = std::any_cast<long>(request.at("productId"));
|
||
int quantity = std::any_cast<int>(request.at("quantity"));
|
||
std::string address = request.count("address") ? std::any_cast<std::string>(request.at("address")) : "默认收货地址";
|
||
Order order = businessService.createOrderDirect(CURRENT_USER_ID, productId, quantity, address);
|
||
return ResponseEntity<Order>::created(order);
|
||
}
|
||
|
||
ResponseEntity<Order> getOrderById(long id) {
|
||
return ResponseEntity<Order>::ok(businessService.getOrderById(CURRENT_USER_ID, id));
|
||
}
|
||
|
||
ResponseEntity<Order> cancelOrder(long id) {
|
||
return ResponseEntity<Order>::ok(businessService.cancelOrder(CURRENT_USER_ID, id));
|
||
}
|
||
|
||
// ==================== 退款 ====================
|
||
ResponseEntity<Refund> applyRefund(const std::map<std::string, std::any>& request) {
|
||
long orderId = std::any_cast<long>(request.at("orderId"));
|
||
std::string reason = request.count("reason") ? std::any_cast<std::string>(request.at("reason")) : "七天无理由退货";
|
||
Refund refund = businessService.applyRefund(CURRENT_USER_ID, orderId, reason);
|
||
return ResponseEntity<Refund>::created(refund);
|
||
}
|
||
};
|
||
|
||
// 测试用例开始
|
||
TEST(BusinessControllerTest, testGetProductByIdNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
Product expectedProduct;
|
||
expectedProduct.id = 101;
|
||
expectedProduct.name = "iPhone 15";
|
||
expectedProduct.price = 7999.0;
|
||
|
||
EXPECT_CALL(mockService, getProductById(101)).Times(1).WillOnce(testing::Return(expectedProduct));
|
||
|
||
auto response = controller.getProductById(101);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
EXPECT_EQ(response.body.id, 101);
|
||
EXPECT_EQ(response.body.name, "iPhone 15");
|
||
EXPECT_DOUBLE_EQ(response.body.price, 7999.0);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testGetProductByIdBoundaryValue) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
Product expectedProduct;
|
||
expectedProduct.id = 0;
|
||
expectedProduct.name = "Test Product";
|
||
expectedProduct.price = 0.0;
|
||
|
||
EXPECT_CALL(mockService, getProductById(0)).Times(1).WillOnce(testing::Return(expectedProduct));
|
||
|
||
auto response = controller.getProductById(0);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
EXPECT_EQ(response.body.id, 0);
|
||
EXPECT_EQ(response.body.name, "Test Product");
|
||
EXPECT_DOUBLE_EQ(response.body.price, 0.0);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testGetProductByIdInvalidInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
EXPECT_CALL(mockService, getProductById(-1)).Times(1).WillOnce(testing::Return(Product{}));
|
||
|
||
auto response = controller.getProductById(-1);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testAddToCartNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["productId"] = 101L;
|
||
request["quantity"] = 2;
|
||
|
||
CartItem expectedItem;
|
||
expectedItem.id = 1001;
|
||
expectedItem.productId = 101;
|
||
expectedItem.quantity = 2;
|
||
expectedItem.totalPrice = 15998.0;
|
||
|
||
EXPECT_CALL(mockService, addToCart(1L, 101L, 2)).Times(1).WillOnce(testing::Return(expectedItem));
|
||
|
||
auto response = controller.addToCart(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.id, 1001);
|
||
EXPECT_EQ(response.body.productId, 101);
|
||
EXPECT_EQ(response.body.quantity, 2);
|
||
EXPECT_DOUBLE_EQ(response.body.totalPrice, 15998.0);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testAddToCartZeroQuantity) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["productId"] = 101L;
|
||
request["quantity"] = 0;
|
||
|
||
CartItem expectedItem;
|
||
expectedItem.id = 1001;
|
||
expectedItem.productId = 101;
|
||
expectedItem.quantity = 1; // 服务层可能默认为1
|
||
expectedItem.totalPrice = 7999.0;
|
||
|
||
EXPECT_CALL(mockService, addToCart(1L, 101L, 1)).Times(1).WillOnce(testing::Return(expectedItem));
|
||
|
||
auto response = controller.addToCart(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.quantity, 1);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testAddToCartNullProductId) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["productId"] = 0L;
|
||
request["quantity"] = 1;
|
||
|
||
EXPECT_CALL(mockService, addToCart(1L, 0L, 1)).Times(1).WillOnce(testing::Return(CartItem{}));
|
||
|
||
auto response = controller.addToCart(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testCreateOrderNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::string> request;
|
||
request["address"] = "北京市朝阳区";
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2001;
|
||
expectedOrder.userId = 1;
|
||
expectedOrder.address = "北京市朝阳区";
|
||
expectedOrder.status = "待支付";
|
||
|
||
EXPECT_CALL(mockService, createOrderFromCart(1L, "北京市朝阳区")).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.createOrder(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.id, 2001);
|
||
EXPECT_EQ(response.body.address, "北京市朝阳区");
|
||
EXPECT_EQ(response.body.status, "待支付");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testCreateOrderEmptyAddress) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::string> request;
|
||
request["address"] = "";
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2001;
|
||
expectedOrder.userId = 1;
|
||
expectedOrder.address = "默认收货地址";
|
||
expectedOrder.status = "待支付";
|
||
|
||
EXPECT_CALL(mockService, createOrderFromCart(1L, "默认收货地址")).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.createOrder(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.address, "默认收货地址");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testBuyDirectNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["productId"] = 101L;
|
||
request["quantity"] = 3;
|
||
request["address"] = "上海市浦东新区";
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2002;
|
||
expectedOrder.userId = 1;
|
||
expectedOrder.address = "上海市浦东新区";
|
||
expectedOrder.status = "待支付";
|
||
|
||
EXPECT_CALL(mockService, createOrderDirect(1L, 101L, 3, "上海市浦东新区")).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.buyDirect(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.id, 2002);
|
||
EXPECT_EQ(response.body.address, "上海市浦东新区");
|
||
EXPECT_EQ(response.body.status, "待支付");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testBuyDirectZeroQuantity) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["productId"] = 101L;
|
||
request["quantity"] = 0;
|
||
request["address"] = "广州市天河区";
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2002;
|
||
expectedOrder.userId = 1;
|
||
expectedOrder.address = "广州市天河区";
|
||
expectedOrder.status = "待支付";
|
||
|
||
EXPECT_CALL(mockService, createOrderDirect(1L, 101L, 1, "广州市天河区")).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.buyDirect(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.status, "待支付");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testGetOrderByIdNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2001;
|
||
expectedOrder.userId = 1;
|
||
expectedOrder.address = "北京市朝阳区";
|
||
expectedOrder.status = "已发货";
|
||
|
||
EXPECT_CALL(mockService, getOrderById(1L, 2001)).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.getOrderById(2001);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
EXPECT_EQ(response.body.id, 2001);
|
||
EXPECT_EQ(response.body.status, "已发货");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testGetOrderByIdNonexistentId) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
EXPECT_CALL(mockService, getOrderById(1L, 9999)).Times(1).WillOnce(testing::Return(Order{}));
|
||
|
||
auto response = controller.getOrderById(9999);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testCancelOrderNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2001;
|
||
expectedOrder.status = "已取消";
|
||
|
||
EXPECT_CALL(mockService, cancelOrder(1L, 2001)).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.cancelOrder(2001);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
EXPECT_EQ(response.body.status, "已取消");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testCancelOrderInvalidStatus) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
Order expectedOrder;
|
||
expectedOrder.id = 2001;
|
||
expectedOrder.status = "已完成";
|
||
|
||
EXPECT_CALL(mockService, cancelOrder(1L, 2001)).Times(1).WillOnce(testing::Return(expectedOrder));
|
||
|
||
auto response = controller.cancelOrder(2001);
|
||
|
||
EXPECT_EQ(response.statusCode, 200);
|
||
EXPECT_EQ(response.body.status, "已完成");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testApplyRefundNormalInput) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["orderId"] = 2001L;
|
||
request["reason"] = "商品有瑕疵";
|
||
|
||
Refund expectedRefund;
|
||
expectedRefund.id = 3001;
|
||
expectedRefund.orderId = 2001;
|
||
expectedRefund.reason = "商品有瑕疵";
|
||
expectedRefund.status = "审核中";
|
||
|
||
EXPECT_CALL(mockService, applyRefund(1L, 2001L, "商品有瑕疵")).Times(1).WillOnce(testing::Return(expectedRefund));
|
||
|
||
auto response = controller.applyRefund(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.id, 3001);
|
||
EXPECT_EQ(response.body.reason, "商品有瑕疵");
|
||
EXPECT_EQ(response.body.status, "审核中");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testApplyRefundDefaultReason) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["orderId"] = 2001L;
|
||
|
||
Refund expectedRefund;
|
||
expectedRefund.id = 3001;
|
||
expectedRefund.orderId = 2001;
|
||
expectedRefund.reason = "七天无理由退货";
|
||
expectedRefund.status = "审核中";
|
||
|
||
EXPECT_CALL(mockService, applyRefund(1L, 2001L, "七天无理由退货")).Times(1).WillOnce(testing::Return(expectedRefund));
|
||
|
||
auto response = controller.applyRefund(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
EXPECT_EQ(response.body.reason, "七天无理由退货");
|
||
}
|
||
|
||
TEST(BusinessControllerTest, testApplyRefundInvalidOrderId) {
|
||
MockBusinessService mockService;
|
||
BusinessController controller(mockService);
|
||
|
||
std::map<std::string, std::any> request;
|
||
request["orderId"] = -1L;
|
||
request["reason"] = "质量问题";
|
||
|
||
EXPECT_CALL(mockService, applyRefund(1L, -1L, "质量问题")).Times(1).WillOnce(testing::Return(Refund{}));
|
||
|
||
auto response = controller.applyRefund(request);
|
||
|
||
EXPECT_EQ(response.statusCode, 201);
|
||
} |