using System;
using Moq;
namespace MoqSample
{
class Program
{
static void Main(string[] args)
{
// ARRANGE
decimal amount = 100;
// that's why you will love unit testing, mishaps could be avoided :-)
string errorMessage = "Could be an anomaly, passed amount is different from amount to transfer";
var mockedSource = new Mock<IAccount>();
mockedSource.Setup(x => x.Withdraw(It.Is<decimal>(a => a != amount))).Throws(new Exception(errorMessage));
mockedSource.Setup(x => x.Deposit(It.Is<decimal>(a => a != amount))).Throws(new Exception(errorMessage));
var mockedDest = new Mock<IAccount>();
mockedDest.Setup(x => x.Withdraw(It.Is<decimal>(a => a != amount))).Throws(new Exception(errorMessage));
mockedDest.Setup(x => x.Deposit(It.Is<decimal>(a => a != amount))).Throws(new Exception(errorMessage));
// ACT
int test = 0;
/*
* 0's error: NONE
*
* 1's error:
* Expected invocation on the mock should never have been performed, but was 1 times: source => source.Deposit(.amount)
*
* 2's error:
* Expected invocation on the mock once, but was 2 times: dest => dest.Deposit(.amount)
*
* 3's error:
* Expected invocation on the mock once, but was 0 times: dest => dest.Deposit(.amount)
*
* 4's error:
* Expected invocation on the mock once, but was 0 times: source => source.Withdraw(.amount)
*
* 5's error:
* Could be an anomaly, passed amount is different from transfer amount
*
* */
if (test == 0)
TransactionMaker.TransferFund(mockedSource.Object, mockedDest.Object, amount);
else if (test == 1)
TransactionMaker.TransferFundBuggy1(mockedSource.Object, mockedDest.Object, amount);
else if (test == 2)
TransactionMaker.TransferFundBuggy2(mockedSource.Object, mockedDest.Object, amount);
else if (test == 3)
TransactionMaker.TransferFundBuggy3(mockedSource.Object, mockedDest.Object, amount);
else if (test == 4)
TransactionMaker.TransferFundBuggy4(mockedSource.Object, mockedDest.Object, amount);
else if (test == 5)
TransactionMaker.TransferFundAnomalous(mockedSource.Object, mockedDest.Object, amount);
else
throw new Exception("Select test case from 0 to 5");
// ASSERT
mockedSource.Verify(source => source.Withdraw(amount), Times.Once());
mockedSource.Verify(source => source.Deposit(amount), Times.Never());
mockedDest.Verify(dest => dest.Deposit(amount), Times.Once());
mockedDest.Verify(dest => dest.Withdraw(amount), Times.Never());
}
}
public static class TransactionMaker
{
public static void TransferFund(IAccount sourceAccount, IAccount destAccount, decimal amountToTransfer)
{
sourceAccount.Withdraw(amountToTransfer);
destAccount.Deposit(amountToTransfer);
}
public static void TransferFundBuggy1(IAccount sourceAccount, IAccount destAccount, decimal amountToTransfer)
{
sourceAccount.Withdraw(amountToTransfer);
sourceAccount.Deposit(amountToTransfer);
}
public static void TransferFundBuggy2(IAccount sourceAccount, IAccount destAccount, decimal amountToTransfer)
{
sourceAccount.Withdraw(amountToTransfer);
destAccount.Deposit(amountToTransfer);
destAccount.Deposit(amountToTransfer);
}
public static void TransferFundBuggy3(IAccount sourceAccount, IAccount destAccount, decimal amountToTransfer)
{
sourceAccount.Withdraw(amountToTransfer);
}
public static void TransferFundBuggy4(IAccount sourceAccount, IAccount destAccount, decimal amountToTransfer)
{
sourceAccount.Deposit(amountToTransfer);
}
public static void TransferFundAnomalous(IAccount sourceAccount, IAccount destAccount, decimal amountToTransfer)
{
sourceAccount.Withdraw(amountToTransfer);
destAccount.Deposit(amountToTransfer + 0.5M);
}
}
public interface IAccount
{
void Withdraw(decimal v);
void Deposit(decimal v);
}
public class Account : IAccount
{
public void Withdraw(decimal amount)
{
}
public void Deposit(decimal amount)
{
}
}
}
"Simplicity can't be bought later, it must be earned from the start" -- DB
Monday, February 27, 2012
A primer on unit testing with Moq
The following code is a primer on unit testing, just get Moq from Nuget. Note: Actual unit testing should be done on a separate project, not on Main method :-) This code just demonstrates how elegant Moq is for unit testing needs.
Subscribe to:
Comments (Atom)