简体   繁体   中英

Mocking an interface that extends another interface using Moq

Hej Buddies!

I'm trying to create a mock for an interface like the one below:

public interface ITheInterface: IEnumerable
{
...
}

In these manners:

var theInterfaceMock = new Mock<ITheInterface>();
theInterfaceMock.Setup(x => x.OfType<SomeType>()).Returns(something);

and

var theInterfaceMock = new Mock<ITheInterface>();
theInterfaceMock.As<IEnumerable>();
theInterfaceMock.Setup(x => x.OfType<SomeType>()).Returns(something);

And in both cases I'm getting a System.NotSupportedException that basically tells me that that ITheInterface doesn't have the OfType() method (when it actually does have it). Anybody knows any way to solve this issue?.

Thank you!

OfType is not a method on the IEnumerable, it's an extension method called Enumberable.OfType .

This is why Moq is complaining I think. Since these are static classes, I think you'll need to use a tool like typemock .

Question is however. Why you need to mock OfType()? You can trust that the microsoft implementation of Enumberable.OfType works. So just mock the the IEnumberable interface (GetEnumerator) , and return a mock that support IEnumerator, that OfType will use.

IEnumerable has no method named OfType ... are you looking for IEnumerable? - Even there OfType is just an extension method and you would have to mock the Enumerable-class and it's static members. I don't think Moq can do this - sorry.

Here are some related questions (with possible workarounds): How do I use Moq to mock an extension method? and Mock static property with moq

I believe the issue here is that OfType is an extension method. Since Moq (and other mocking frameworks) work by creating proxy objects/classes of the interfaces being mocked, it only has the ability to mock instance methods. Extension methods are just static methods in disguise.

As other already told OfType is not a method of the IEnumerable interface. However, you don't really need to mock it, all you need is to mock IEnumerable.GetEnumerator method which is pretty easy to do:


    var enumerable = new Mock<IEnumerable>();
    var something = new List<SomeType>
    {
        new SomeType(),
        new SomeType(),
        new SomeType(),
    };
    enumerable.Setup(_ => _.GetEnumerator()).Returns(something.GetEnumerator());

    Assert.That(enumerable.Object.OfType<SomeType>(), Is.EquivalentTo(something));

You just forward GetEnumerator method to one of the 'something' collection and that is all. You'll get all extension methods working for your mock automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM