• 单元测试之Mock(Moq)


    Mock翻译为“嘲弄”,其实就是伪造一个对象用于测试。在单元测试中,被测试方法依赖于其他对象时,为了测试简单一般“伪造”一个这个对象;这样做的目的:

    • 不用考虑依赖对象的复杂性(方便准备测试数据)
    • 只专注测试被测试方法,不将单元测试扩充到测试依赖对象

    打折算法测试

    商场中的商品类:

        public class Product {
            public int ProductID { get; set; }
            public string Name { get; set; }
            public string Description { get; set; }
            public decimal Price { get; set; }
            public string Category { set; get; }
        }
    

    打折接口:

        public interface IDiscountHelper {
            decimal ApplyDiscount(decimal totalParam);
        }
    

    被测试的打折算法

        public class LinqValueCalculator : IValueCalculator {
            private IDiscountHelper discounter;
    
            public LinqValueCalculator(IDiscountHelper discountParam) {
                discounter = discountParam;
            }
    
            public decimal ValueProducts(IEnumerable<Product> products) {
                return discounter.ApplyDiscount(products.Sum(p => p.Price));
            }
    

    显然,被测试方法ValueProducts依赖打折接口IDiscountHelper,这里通过伪造一个实现IDiscountHelper接口的对象。

    Moq功能介绍

    1. 创建伪造对象
      Mock<IDiscountHelper> mock = new Mock<IDiscountHelper>();

    2. 设置伪造对象的方法
      mock.Setup(m => m.ApplyDiscount(It.IsAny<decimal>()))

    3. 参数限制
      t.IsAny<decimal>()通过It限制这里列出几个

      限制表达式 解释 例子
      It.Is(predicate) 通过predicate返回bool值判断限制测试 It.Is<decimal>(v => v == 0)
      It.IsAny() T类型的任意值 It.IsAny()
      It.IsInRange(TValue from, TValue to, Range rangeKind) T类型参数的值在范围内或外(rangeKind参数决定) It.IsInRange<int>(1, 100, Range.Inclusive)
    4. 设置返回值
      .Returns<decimal>(total => total);

    构造单元测试

        [TestClass]
        public class UnitTest2 {
    
            private Product[] createProduct(decimal value) {
                return new[] { new Product { Price = value } };
            }
    
            [TestMethod]
            [ExpectedException(typeof(System.ArgumentOutOfRangeException))]
            public void Pass_Through_Variable_Discounts() {
                // arrange
                Mock<IDiscountHelper> mock = new Mock<IDiscountHelper>();
                mock.Setup(m => m.ApplyDiscount(It.IsAny<decimal>()))
                    .Returns<decimal>(total => total);
                mock.Setup(m => m.ApplyDiscount(It.Is<decimal>(v => v == 0)))
                    .Throws<System.ArgumentOutOfRangeException>();
                mock.Setup(m => m.ApplyDiscount(It.Is<decimal>(v => v > 100)))
                    .Returns<decimal>(total => (total * 0.9M));
                mock.Setup(m => m.ApplyDiscount(It.IsInRange<decimal>(10, 100,
                    Range.Inclusive))).Returns<decimal>(total => total - 5);
                var target = new LinqValueCalculator(mock.Object);
    
                // act
                decimal FiveDollarDiscount = target.ValueProducts(createProduct(5));
                decimal TenDollarDiscount = target.ValueProducts(createProduct(10));
                decimal FiftyDollarDiscount = target.ValueProducts(createProduct(50));
                decimal HundredDollarDiscount = target.ValueProducts(createProduct(100));
                decimal FiveHundredDollarDiscount = target.ValueProducts(createProduct(500));
    
                // assert
                Assert.AreEqual(5, FiveDollarDiscount, "$5 Fail");
                Assert.AreEqual(5, TenDollarDiscount, "$10 Fail");
                Assert.AreEqual(45, FiftyDollarDiscount, "$50 Fail");
                Assert.AreEqual(95, HundredDollarDiscount, "$100 Fail");
                Assert.AreEqual(450, FiveHundredDollarDiscount, "$500 Fail");
                target.ValueProducts(createProduct(0));
            }
        }
    
  • 相关阅读:
    第四次作业—四则运算
    第四次作业—代码规范
    【欢迎来怼】事后诸葛亮会议
    软件工程——第七次作业
    第17次Scrum会议(10/29)【欢迎来怼】
    软件工程——第六次作业
    第10次Scrum会议(10/22)【欢迎来怼】
    软件工程——第五次作业
    欢迎来怼——第四次Scrum会议
    软件工程——第四次作业(3)
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/9842745.html
Copyright © 2020-2023  润新知