【问题标题】:Unit test for update method in C# using Mock使用 Mock 对 C# 中的更新方法进行单元测试
【发布时间】:2020-02-02 07:09:06
【问题描述】:

我正在尝试为我的处理器类编写单元测试我有两个问题

  • 我不知道如何仅测试我的方法。 这是我的处理器


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


        }

这是我的单元测试,我不知道如何解决它,问题到底出在哪里,我也想测试方法。

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

【问题讨论】:

  • 嗨 Nazaning,人们通常很难审查大型代码,我建议将您的问题减少到可以轻松复制的范围内。
  • 谢谢你,我按照你说的做了,希望现在更好。
  • @Nazanin 目前状态下的问题不完整,因此不清楚。如果您可以用minimal reproducible example 重新格式化问题,那就太好了,这样我们就可以更清楚地了解当前的问题以及您实际上要做什么?请参阅How to Ask 页面以获得澄清此问题的帮助。

标签: c# unit-testing mocking


【解决方案1】:

在您的代码中,我看到有各种各样的模拟和初始测试设置正在发生,而没有明确的测试意图。

单元测试:什么?

在没有外部依赖

的情况下测试应用程序的一个单元

单元测试:为什么?

加快重构速度并确保不会破坏代码的现有部分

单元测试:步骤?

  • 在进行单元测试之前,我们首先需要重构代码。模块化是关键
  • 通过使用接口删除代码中的紧密耦合
  • 通过方法参数、构造函数、属性注入依赖或使用依赖注入
  • 考虑将 Mock 对象作为一种良好做法,仅在处理外部依赖项时使用。
  • [TestMethod] 中,我们将测试分为 3 个类别Arrange -> Act -> Assert

    例子:

    //Arrange 
    var res = new Reservation();
    
    //Act
    var op = res.Method(new User{IsAdmin=true});
    
    // Assert
    Assert.IsTrue(op);
    

单元测试中的命名约定:

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中添加StackOrderProcessor的引用

您仍然需要更好地组织单元测试方法,这只是为了演示目的,我希望现在概念更加清晰

【讨论】:

    【解决方案2】:

    您的问题没有足够的信息,您不需要此问题的存储库代码,但需要 OrderBuiler 类和 _orders 字段。对于答案位置的这条评论,我深表歉意。

    【讨论】:

    • - 当然,我会试试
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2015-09-16
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多