boom/tests/test_BusinessController.cpp

459 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}