In this blog post, I will show you some tips and tricks for Moq
a framework. Like how to moq protected method, and how to moq async method with some real-world example. Before diving into the code let’s get familiar with some basic terms.
Why Mocking?
Moq is commonly used to create mock objects based on interfaces.
However, in some cases, Moq allows creating Moq of the classes that are called Partial Moq.
What is a Partial Mock?
Partial mocking is where you take a class and ask it to behave as usual, except you want to override certain functionality.
Example
This post will show you how to mock the async protected method in C# using the MOQ framework. The mocking protected method is a little bit tricky, but it’s straightforward.
public class ServiceHelper
{
public async Task<string> GetData(string url)
{
var result = await SendRequest(url);
Console.WriteLine("Doing some real work");
return result;
}
protected virtual async Task<string> SendRequest(string url)
{
Console.WriteLine($"Sending Request to {url}");
var result = await Task.FromResult("From Protected Method");
return result;
}
}
Let’s write a unit test for the public method.
public class ServiceHelperTest
{
[Fact]
public async Task Should_call_protected_method()
{
var p = new ServiceHelper();
var data = await p.GetData("https://jsonplaceholder.typicode.com/todos/1");
Assert.Contains(data,"From Protected Method");
}
}
As you can see, the test is calling the actual protected method.
Let’s create a mock of the class and set up the behavior; as shown in the image below, IntelliSense is not showing the protected method. So let’s run the test without setup and see the result.
]
[Fact]
public async Task Should_throw_error_if_call_on_mock_object()
{
var mockService = new Mock<ServiceHelper>();
var data = await mockService.Object.GetData("https://jsonplaceholder.typicode.com/todos/1");
Assert.Contains(data, "From Protected Method");
}
You will get the following error
[FAIL] ServiceHelperTest.Should_throw_error_if_call_on_mock_object:
Value cannot be null. (Parameter 'value')
How to mock the protected method
. To Mock the protected method, you need to import the following namespace first.
using Moq.Protected;
[Fact]
public async Task Should_call_mock_method()
{
var mockService = new Mock<ServiceHelper>();
mockService.Protected().Setup<Task<string>>("SendRequest", ItExpr.IsAny<string>()).ReturnsAsync(() => "From Mock")
.Verifiable();
var result = await mockService.Object.GetData("https://jsonplaceholder.typicode.com/todos/1");
Assert.Contains(result,"From Mock");
mockService.Verify();
}
If you run the above test case, you can see that it’s calling the Moq method, and the test is pass.
Limitations
-
Only drawback with this API is that you will not get the IntelliSense when setup the moq
-
When setting up an
IProtectedMock
, you should useMoq.Protected.ItExpr
instead ofMoq. It
.