Overview

Credit: https://docs.educationsmediagroup.com/unit-testing-csharp/moq Credit: https://softchris.github.io/pages/dotnet-moq.html#creating-our-first-mock

Mocks are configured using the Setup() and Returns() methods. This configuration, also known as instruction, tells the mock to answer with a certain response if a method or property is called.

Some test examples below use this system:

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);
} 

And are arranged like this:

var mock = new Mock<IFoo>();
mock.Setup(p => p.DoSomething(It.IsAny<string>())).Returns(true);
var sut = new Service(mock.Object);

Configuring Method Calls

When the DoSomething() method is called with argument "ping", the method should return true:

mock.Setup(mock => mock.DoSomething("ping")).Returns(true);

Repeated Calls

To test methods that should have different outcomes when called repeatedly:

mock.SetupSequence(p => p.GetSomething(It.IsAny<string>())
    .Returns(1)
    .Returns(2)
    .Returns(3);

If the method returns void, replace Returns(arg) with Pass().

out Parameters

When TryParse() is called with argument "ping", it should set the out parameter to "ack" and return true:

var outString = "ack";
mock.Setup(mock => mock.TryParse("ping", out outString)).Returns(true);

ref Parameters

Only matches if the ref argument to the invocation is the same instance:

var instance = new Bar();
mock.Setup(mock => mock.Submit(ref instance)).Returns(true);

Or:

var value = "This is a test value";
mock.Setup(p => p.DoSomething(ref value));

Async Methods

Use the Task’s Result property:

mock.Setup(mock => mock.DoSomethingAsync().Result).Returns(true);

Or, use ReturnsAsync():

mock.Setup(p => p.GetValueAsync()).ReturnsAsync(123);

Methods with Computed Return Values

For this scenario, both Returns() and ReturnsAsync() have overloads that accept a delegate:

mock.Setup(p => p.Add(It.IsAny<int>(), It.IsAny<int>())
    .Returns((int first, int second) => first + second);

Methods That Throw Exceptions

mock.Setup(p => p.DoSomething()).Throws<Exception>());

mock.Setup(p => p.DoSomethingAsync()).ThrowsAsync(new Exception());

Configuring Mocked Delegates

Consider this delegate:

public delegate int ParseString(string value);

To mock it:

var mock = new Mock<ParseString>();

mock.Setup(p => p(It.IsAny<string>()))
    .Returns(42);