What is it?
- Generate objects (instances) based on interfaces
- Declaratively define the behavior of generated object
- Use Nuget to add Moq to your project
Example
- We want to unit test the invoice class.
- We want to "fix" the behavior of shipping and tax calculation classes so that we can truly exercise and test the functionality of invoice class in isolation
Code to Test
public class Invoice
{
IShippingCalc _shippingCalc;
ITaxCalc _taxCalc;
decimal _subTotal;
string _state;
public Invoice(decimal subTotal, string state, IShippingCalc shippingCalc,
ITaxCalc taxCalc)
{
this._state = state;
this._shippingCalc = shippingCalc;
this._taxCalc = taxCalc;
this._subTotal = subTotal;
}
public decimal TotalDue
{
get
{
return _subTotal + _shippingCalc.Calc(_state) + _taxCalc.CalcTax(_state, _subTotal);
}
}
}
public interface IShippingCalc
{
decimal Calc(string state);
}
public interface ITaxCalc
{
decimal CalcTax(string state, decimal taxableAmount);
}
Unit Test
- We create "mocks" for IShippingCalc and ITaxCalc using Moq
- We define the behavior of these mocked objects so that we can verify the behavior of the invoice class
public void BasicInvoiceTest()
{
var shippingMoq = new Mock<IShippingCalc>();
shippingMoq.Setup(
m => m.Calc(
It.Is<string>(state =>
state.Equals("ca", StringComparison.InvariantCultureIgnoreCase)))).Returns(5);
shippingMoq.Setup(
m => m.Calc(
It.Is<string>(state =>
!state.Equals("ca", StringComparison.InvariantCultureIgnoreCase)))).Returns(10);
var taxMoq = new Mock<ITaxCalc>();
taxMoq.Setup( // no sales tax for other states
m => m.CalcTax(It.IsAny<String>(), It.IsAny<decimal>()))
.Returns<string, decimal>((s, d) => 0);
taxMoq.Setup( // 8% sales tax for CA
m => m.CalcTax(It.IsIn("ca", "CA", "Ca", "ca"), It.IsAny<decimal>()))
.Returns((string state, decimal taxableAmount) => taxableAmount * .08M);
var subTotal = 100;
var invoiceCA = new Invoice(subTotal, "ca", shippingMoq.Object, taxMoq.Object);
Assert.AreEqual((100 + 8 + 5), invoiceCA.TotalDue, "subTotal + Sales Tax + $5 shipping");
var invoiceOther = new Invoice(subTotal, "ma", shippingMoq.Object, taxMoq.Object);
Assert.AreEqual((100 + 0 + 10), invoiceOther.TotalDue, "subTotal + NO Tax + $10 shipping");
}