A mocking framework like Moq does not completely replace the testing framework's Assert
. sometimes it does, sometimes it doesn't.
Let's first distinguish between mocks and stubs. Stubs are used purely for isolation and to inject some sort of controlled behaviour into system under test (SUT).
Mocks are a superset of stubs and are able to verify whether or not something was called on a mock. In Moq, an invocation of Verify()
makes stub a mock with respect to that method. Calling VerifyAll()
makes all methods that were set up mocks.
The recommended approach is that you should have no more than one mock in your test. In that sense, it is similar to Assert
- that you shouldn't be verifying more than one thing in a test.
Coming back to the original question. If you are performing state testing, than you would use zero or more stubs and one assert. If you are doing interaction testing, than you would use zero or more stubs and one mock. Below is an example where it might be appropriate to use both mocks and asserts to test the same service.
public interface IAccountRepository {
decimal GetBalance(int accountId);
void SetBalance(int accountId, decimal funds);
}
public class DepositTransaction {
IAccountRepository m_repo;
public DepositTransaction(IAccountRepository repo) {
m_repo = repo;
}
public decimal DepositedFunds {get; private set;};
void Deposit(int accountId, decimal funds) {
decimal balance = m_repo.GetBalance(accountId);
balance += funds;
m_repo.SetBalance(balance);
DepositedFunds += funds;
}
}
public class DepositTest {
[TestMethod]
void DepositShouldSetBalance() {
var accountMock = new Mock<IAccountRepository>();
accountMock.Setup(a=>a.GetBalance(1)).Returns(100); //this is a stub with respect to GetBalance
var transation = new DepositTransaction(accountMock.Object);
transation.Deposit(1, 20);
accountMock.Verify(a=>a.SetBalance(1, 120)); //this is a mock with respect to SetBalance
}
[TestMethod]
void DepositShouldIncrementDepositedFunds() {
var accountMock = new Mock<IAccountRepository>();
accountMock.Setup(a=>a.GetBalance(1)).Returns(100); //this is a stub with respect to GetBalance
var transation = new DepositTransaction(accountMock.Object);
transation.Deposit(1, 20);
transation.Deposit(1, 30);
Assert.AreEqual(50, transaction.DepositedFunds);
}
}