本文介绍了使用 Mock 对 C# 中的更新方法进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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# 中的更新方法进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-14 06:42