Mock is translated as "Mocking". In fact, it is to forge an object for testing. In unit testing, when the method to be tested depends on other objects, this object is generally "forged" for test simplicity:
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; } }
Discount interface:
public interface IDiscountHelper { decimal ApplyDiscount(decimal totalParam); }
Discount algorithm tested
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)); }
Obviously, the method to be testedValueProducts
Discount InterfaceIDiscountHelper
Here, by forging an implementationIDiscountHelper
Interface object.
Moq features
- Create forged object
Mock<IDiscountHelper> mock = new Mock<IDiscountHelper>();
- Method for setting forged objects
mock.Setup(m => m.ApplyDiscount(It.IsAny<decimal>()))
Parameter restrictions
t.IsAny<decimal>()
PassIt
Restrictions:
Limit expression |
Explanation |
Example |
It. Is |
Test the bool value returned by Predicate |
It.Is<decimal>(v => v == 0) |
It. isany |
Any value of the T Type |
It.IsAny() |
It. isinrange |
The value of the T type parameter is within or outside the range (determined by the rangekind parameter) |
It.IsInRange<int>(1, 100, Range.Inclusive) |
Set Return Value
.Returns<decimal>(total => total);
Construct unit test
[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)); } }
Mock (Moq) for unit testing)