Abstract [ Documentation]
Moq is a simple, minimalistic mocking framework.
Installation
dotnet add package Moq
In test project:
using Moq;
// If mocking a class with a protected member:
using Moq.Protected;
Overview
Assumptions
Assume this interface:
public interface IDateTimeProvider
{
DayOfWeek DayOfWeek();
string Name { get; set; }
}
Assume a concrete class with one method with two overloads:
public class RateCalculator
{
public decimal GetPayRate(decimal baseRate)
{
return DateTime.Now.DayOfWeek == DayOfWeek.Sunday ?
baseRate * 1.25m :
baseRate;
}
public decimal GetPayRate(decimal baseRate, IDateTimeProvider dateTimeProvider)
{
return dateTimeProvider.DayOfWeek() == DayOfWeek.Sunday ?
baseRate * 1.25m :
baseRate;
}
}
Arrange
The RateCalculator
is the system under test:
var rateCalculator = new RateCalculator();
Create a mock:
var dateTimeProviderMock = new Mock<IDateTimeProvider>();
Instruct the mock with Moq’s Setup()
method such that when its DayOfWeek()
method is called, it returns DayOfWeek.Sunday
:
dateTimeProviderMock.Setup(m => m.DayOfWeek()
.Returns(DayOfWeek.Sunday);
Act
Call the instance of the system under test with the mocked object using the mock’s Object
property:
var actual = rateCalculator.GetPayRate(10.00m, dateTimeProviderMock.Object);
Assert
Use Moq’s Verify()
method to verify that the mocked object’s method ran, and then assert:
dateTimeProviderMock.Verify(m => m.DayOfWeek(), Times.Once());
Assert.That(actual, Is.EqualTo(12.5m));
Another Example
Credit: https://docs.educationsmediagroup.com/unit-testing-csharp/moq/quick-glance-at-moq
Consider this service and interface:
public class Service
{
private readonly IFoo _foo;
public Service(IFoo foo) => _foo = foo ?? throw new ArgumentNullException(nameof(foo));
public void Ping() => _foo.DoSomething("PING");
}
public interface IFoo
{
bool DoSomething(string command);
}
The test:
[Test]
public void Ping_invokes_DoSomething()
{
// ARRANGE
// Get the mock:
var mock = new Mock<IFoo>();
// Set it up:
mock.Setup(p => p.DoSomething(It.IsAny<string>())).Returns(true);
// Get the system under test by invoking a new instance of the service and passing in the mock object:
var sut = new Service(mock.Object);
// ACT
// Run the method being tested on the system under test:
sut.Ping();
// ASSERT
mock.Verify(p => p.DoSomething("PING"), Times.Once());
}
Verification
Verifying Method Calls
Verify a method was called with a specific value:
mock.Verify(foo => foo.DoSomething("ping"));
Same as above but with a custom error message:
mock.Verify(foo => foo.DoSomething("ping"), "Always call DoSomething() with ping argument");
Verify the method was called at least once:
mock.Verify(foo => foo.DoSomething("ping"), Times.AtLeastOnce());
Verify the method was never called:
mock.Verify(foo => foo.DoSomething("ping"), Times.Never());
Verifying Properties
Verify the setter was called with a specific value:
mock.VerifySet(foo => foo.Name = "foo");
Verify the setter was called, regardless of value:
mock.VerifySet(foo => foo.Name);
Verify the setter with an argument matcher:
mock.VerifySet(foo => foo.Value = It.IsInRange(1, 5, Range.Inclusive));
Verify the getter was called, regardless of value:
mock.VerifyGet(foo => foo.Name);
Verifying Event Accessors
mock.VerifyAdd(foo => foo.FooEvent += It.IsAny<EventHandler>());
mock.VerifyRemove(foo => foo.FooEvent -= It.IsAny<EventHandler>());
Verify No Other Invocations
Beyond those already verified:
mock.VerifyNoOtherCalls();
// access invocation arguments when returning a value
mock.Setup(x => x.DoSomethingStringy(It.IsAny