问题描述
我正在尝试为我的处理器类编写单元测试我有两个问题
I am trying to write a unit test for My Processor class I have two problems
- 我不知道如何仅测试我的方法.这是我的处理器
OrderProcessor 类
public class OrderProcessor
{
public void Process(CustomersOrder order)
{
var oldOrder = _repository.GetOldorderId(order.Code.Value);
if (oldOrder != 0)
{
updateOrder(order);
}
else
{
SaveOrder(order);
}
}
private void updateOrder(CustomersOrder order)
{
_repository.UpdateOrder(order);
}
private void SaveOrder(CustomersOrder order)
{
_repository.SaveOrder(order);
}
}
}
存储库类
public class Repository : IRepository
{
private static PracticeEntities4 _context;
public Repository(PracticeEntities4 context)
{
_context = context;
}
public int GetOldCustomerId( int customerCode)
{
var CuID= _context.Customers.First(e => e.Code == customerCode);
return CuID.Id;
}
public int GetOldorderId(int orderCode)
{
var oldOrder = _context.CustomersOrders.FirstOrDefault(e => e.Code == orderCode);
return oldOrder.Id;
}
public void SaveCustomer(Customer customer)
{
_context.Customers.Add(customer);
_context.SaveChanges();
}
public void SaveOrder(CustomersOrder order)
{
_context.CustomersOrders.Add(order);
_context.SaveChanges();
}
public void UpdateOrder(CustomersOrder order)
{
_context.CustomersOrders.AddOrUpdate(order);
_context.SaveChanges();
}
}
这是我的单元测试,我不知道如何解决它,问题到底出在哪里,我也想测试方法.
and this is My unit test I don't know how to fix it and where is the problem exactly and also I want to test the Methods too.
UnitTests 类
[TestClass]
public class OrderProcessorTest
{
[ClassInitialize]
{...}
[TestInitialize]
public void TestInitialize()
{
....
}
[TestMethod]
public void Customer_OrderProcess()
{
//Arange
Mock<IRepository> mock= new Mock<IRepository>();
//Act
mock.Setup(e => e.GetOldCustomerId(1001)).Returns(3);
mock.Setup(e => e.GetOldStoreId(200)).Returns(3);
var dtos = OrderDeserializer.Deserialize(path);
var dto = dtos.First(e => e.Code == 300);
OrderBuilder builder = new OrderBuilder(mock.Object);
builder.OrderBuild(dto);
//Asset
Assert.AreEqual(0, _orders.Count);
}
}
订单生成器类
public class OrderBuilder
{
public IRepository _repository { get; set; }
public OrderBuilder(IRepository repository)
{
_repository = repository;
}
public CustomersOrder OrderBuild(OrderDto dto)
{
var oldStoreId = _repository.GetOldStoreId(dto.StoreCode);
var oldCustomerId = _repository.GetOldCustomerId(dto.CustomerCode);
return new CustomersOrder()
{
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
DeliveryDate = Convert.ToDateTime(dto.DeliveryDate),
CustomerId = oldCustomerId,
StoreId = oldStoreId,
Code = dto.Code
};
}
}
推荐答案
在你的代码中,我看到有各种各样的模拟和初始测试设置正在发生,而没有明确的测试意图.
在没有外部依赖
加快重构速度并确保不会破坏代码的现有部分
- 在进行单元测试之前,我们首先需要重构代码.模块化是关键
- 通过使用接口消除代码中的紧密耦合
- 通过方法参数、构造函数、属性注入依赖或使用依赖注入
- 考虑使用 Mock 对象,作为一种好的做法,仅在处理外部依赖项时.
在
[TestMethod]
中,我们将测试分为3类Arrange -> Act -> Assert
- We first need to re-factor the code before we do unit tests. Modularity is the key
- By using Interfaces remove the tight couplings in the code
- Inject the dependency via method parameters, constructor, properties or use Dependency Injection
- Consider using Mock objects, as a good practice, only when dealing with external dependency.
In the
[TestMethod]
we organize the tests into 3 categories Arrange -> Act -> Assert
例子:
//Arrange
var res = new Reservation();
//Act
var op = res.Method(new User{IsAdmin=true});
// Assert
Assert.IsTrue(op);
TestProjectName: [InserProjectName].UnitTests
测试类: [InsertClassName]测试
测试方法: [MethodYourTesting]_[Scenario]_[ExpectedBehavior]
TestProjectName: [InserProjectName].UnitTests
TestClasses: [InsertClassName]Tests
TestMethod: [MethodYourTesting]_[Scenario]_[ExpectedBehavior]
我创建了一个尽可能接近您的问题的 Console
应用(减去 DBContext),您可以在 PC 上复制以了解各个部分.
所有领域类都是一个单一的一部分为了可测试性而更快地复制.
控制台应用项目
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StackOrderProcessor
{
public class CustomersOrder
{
public OrderDto Order { get; set; }
public List<CustomersOrder> CustomersOrders = new List<CustomersOrder>();
public DateTime OrderDate { get; set; }
public string OrderStatus { get; set; }
public int CustomerID { get; set; }
public int Code { get; set; }
public int ID { get; set; }
}
public class Customer
{
public OrderDto Order { get; set; }
public List<Customer> Customers = new List<Customer>();
public int Code { get; set; }
public int ID { get; set; }
}
public class OrderDto
{
public DateTime OrderDate { get; set; }
public int CustomerCode { get; set; }
public string OrderStatus { get; set; }
public int Code { get; set; }
}
public interface IRepository
{
int GetOldCustomerId(int customerCode);
int GetOldOrderId(int orderCode);
void SaveCustomer(Customer customer);
void SaveOrder(CustomersOrder order);
}
public class Repository : IRepository
{
private readonly Customer _cust;
private readonly CustomersOrder _custOrder;
public Repository(Customer cust, CustomersOrder custOrder )
{
_cust = cust;
_custOrder = custOrder;
}
public int GetOldCustomerId(int customerCode)
{
var cuId = _cust.Customers.First(e => e.Code == customerCode);
return cuId.ID;
}
public int GetOldOrderId(int orderCode)
{
var oId = _custOrder.CustomersOrders.FirstOrDefault(e => e.Code == orderCode);
return oId.ID;
}
public void SaveCustomer(Customer customer)
{
_cust.Customers.Add(customer);
}
public void SaveOrder(CustomersOrder order)
{
_custOrder.CustomersOrders.Add(order);
}
}
public class OrderProcess
{
private readonly IRepository _repository;
public OrderProcess(IRepository repository)
{
_repository = repository;
}
public void Process(CustomersOrder order)
{
var oldOrder = _repository.GetOldOrderId(order.Code);
if (oldOrder == 0)
_repository.SaveOrder(order);
}
}
public class OrderBuilder
{
private readonly IRepository _repository;
public OrderBuilder(IRepository repository)
{
_repository = repository;
}
public CustomersOrder OrderBuild(OrderDto dto)
{
var oldCustomerId = _repository.GetOldCustomerId(dto.CustomerCode);
return new CustomersOrder()
{
Order = dto,
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
ID = oldCustomerId,
CustomerID = oldCustomerId,
Code = dto.Code
};
}
}
class Program
{
static void Main(string[] args)
{
var cust = new Customer();
var custOrder = new CustomersOrder();
#region PopulatingCustomer
//Populating OrderDto
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
//Populating Customer
var customerList = cust.Customers = new List<Customer>();
var customerOrderList = custOrder.CustomersOrders = new List<CustomersOrder>();
var customer1 = new Customer
{
Code = 1,
ID = 1, Order=dto1
};
var customer2 = new Customer
{
Code = 2,
ID = 2,
};
customerList.Add(customer1);
customerList.Add(customer2);
#endregion
#region PopulatingCustomerOrder
var customersOrder1 = new CustomersOrder { Code = 1, CustomerID = 1, ID = 1, Order = dto1, OrderDate = dto1.OrderDate, OrderStatus = dto1.OrderStatus };
customerOrderList.Add(customersOrder1);
#endregion
#region InvokingMethods
//IRepository
IRepository IRepo = new Repository(cust,custOrder);
//OrderProcessor
var orderProcesor = new OrderProcess(IRepo);
//OrderBuilder
var dto2 = new OrderDto { Code = 2, CustomerCode = 2, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var oBuilder = new OrderBuilder(IRepo);
var newCustOrder = oBuilder.OrderBuild(dto2);
customerOrderList.Add(newCustOrder);
#endregion
Console.Read();
}
}
}
单元测试项目
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using StackOrderProcessor;
namespace StackOrderProcessor.UnitTests
{
[TestClass]
public class RepositoryTests
{
[TestMethod]
public void GetOldCustomerId_WhenCalled_ReturnsOId()
{
//Arrange
var cust = new Customer();
var custOrder = new CustomersOrder();
IRepository repo = new Repository(cust,custOrder);
var customerList = cust.Customers = new List<Customer>();
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var customer1 = new Customer
{
Code = 1,
ID = 1,
Order = dto1
};
var customer2 = new Customer
{
Code = 2,
ID = 2,
};
customerList.Add(customer1);
customerList.Add(customer2);
//Act
repo.GetOldCustomerId(1);
//Assert
Assert.AreEqual(1, 1); //Test will Pass as we have a customer of Code 1
}
[TestMethod]
//MethodName_Scenario_Expectedbehavior
public void SaveCustomer_WhenCalled_AddsNewCustomer()
{
var cust = new Customer();
var custOrder = new CustomersOrder();
IRepository repo = new Repository(cust, custOrder);
var customerList = cust.Customers = new List<Customer>();
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var customer1 = new Customer
{
Code = 1,
ID = 1,
Order = dto1
};
var customer2 = new Customer
{
Code = 2,
ID = 2,
};
customerList.Add(customer1);
customerList.Add(customer2);
//Act
var custToSave = new Customer
{
Code = 3,
ID = 3,
Order = null
};
repo.SaveCustomer(custToSave);
//Assert
Assert.AreEqual(3, customerList.Count);
}
}
[TestClass]
public class OrderProcessor1Tests
{
[TestMethod]
public void Process_WhenOrderIsZero_AddsNewCustomerOrder()
{
//Arrange
var cust = new Customer();
var custOrder = new CustomersOrder();
var customerOrderList = custOrder.CustomersOrders = new List<CustomersOrder>();
IRepository repo = new Repository(cust, custOrder);
var orderProcessor = new OrderProcess(repo);
var dto1 = new OrderDto { Code = 1, CustomerCode = 1, OrderDate = DateTime.Now.Date, OrderStatus = "OK" };
var custOrder1 = new CustomersOrder { ID = 1, Code = 1, CustomerID = 1, Order = dto1, OrderDate = dto1.OrderDate, OrderStatus = dto1.OrderStatus };
customerOrderList.Add(custOrder1);
//Act
orderProcessor.Process(custOrder1);
//Assert
Assert.AreEqual(1, customerOrderList.Count);
}
}
}
注意:确保在StackOrderProcessor.UnitTests
您仍然需要更好地组织单元测试方法,这只是为了演示目的,我希望现在概念更加清晰
这篇关于使用 Mock 对 C# 中的更新方法进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!