How to Use Moq to Mock an Extension Method

How do I use Moq to mock an extension method?

Extension methods are just static methods in disguise. Mocking frameworks like Moq or Rhinomocks can only create mock instances of objects, this means mocking static methods is not possible.

How to properly mock extension methods with generics in xUnit?

Assuming you are using MOQ, do not try to mock the extension method.

Since you control the code of the extension method then mock a safe path through the extension method.

The extension uses GetAsync in this case and that is what needs to be mocked assuming that is not an extension as well.

//...

_repository
.Setup(x => x.GetAsync(It.IsAny<Guid>()))
.ReturnsAsync(GetSamplePhase(newGuid));

//...

It will allow the test when exercised to go through GetActiveAsync code and if it fails, also throw the Exceptions etc as described in the code.

Mock extension methods IElasticClient

Per @Olegl answer. It is not possible to Mock extension methods. You need to refactor and get rid of extension methods in order to make it testable

More info here

Creating a Moq of a static extension method from LLBLGen

You started with an extension method and then you created your IWrap interface along with an implementation that uses the extension method. That's perfect.

Now all you need is to inject it into your class, just like IDataAccessAdapterProvider is already injected:

public class QueryHandler
{
private readonly IDataAccessAdapterProvider _dataAccessAdapterProvider;
private readonly IWrap _wrap; //I'm assuming you'll want a different name.

public QueryHandler(IDataAccessAdapterProvider provider, IWrap wrap)
{
_dataAccessAdapterProvider = provider;
_wrap = wrap;
}

(I applied a common convention there. Prefixing the field names with an underscore - _wrap - means that the field and constructor arguments have different names, so you don't need to specify this.wrap. Plus when people see that underscore elsewhere they'll know it's a field.)

Now you can mock the interface:

var mock = new Mock<IWrap>();
var returnedFromMock = new List<int> { 1, 2, 3 };
mock.Setup(x => x.FetchQueryAsync<int>(It.IsAny<IDataAccessAdapter>(), It.IsAny<DynamicQuery<int>>()))
.ReturnsAsync(returnedFromMock);

You mentioned that there is no way you can change the code. I'm not sure which part you can't change, but if you can't change QueryHandler to replace its concrete dependencies then this may just be a cautionary tale about static dependencies.

You have the source code, though. If you can't change the existing class, perhaps you can just create a new one from the existing source code. If someone asks why you duplicated an existing class, just say (tactfully) that you don't want to duplicate code - you'd rather fix the existing one so that it's testable.



Related Topics



Leave a reply



Submit