views:

1917

answers:

4

I am writing a test that depends on the results of an extension method but I don't want a future failure of that extension method to ever break this test. Mocking that result seemed the obvious choice but Moq doesn't seem to offer a way to override a static method (a requirement for an extension method). There is a similar idea with Moq.Protected and Moq.Stub, but they don't seem to offer anything for this scenario. Am I missing something or should I be going about this a different way?

Here is a trivial example that fails with the usual "Invalid expectation on a non-overridable member". This is a bad example of needing to mock an extension method, but it should do.

public class SomeType {
    int Id { get; set; }
}

var ListMock = new Mock<List<SomeType>>();
ListMock.Expect(l => l.FirstOrDefault(st => st.Id == 5))
        .Returns(new SomeType { Id = 5 });

As for any TypeMock junkies that might suggest I use Isolator instead: I appreciate the effort since it looks like TypeMock could do the job blindfolded and inebriated, but our budget isn't increasing any time soon.

+6  A: 

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.

Mendelt
+4  A: 

If you control the definition of the extension methods (i.e. they are not the LINQ built-in ones), there's another alternative, explained at http://www.clariusconsulting.net/blogs/kzu/archive/2009/02/19/Makingextensionmethodsamenabletomocking.aspx "Making extension methods amenable to mocking"

kzu
Doesn't that entirely remove the usefulness of an extension method? It definitely does allow testing, but so would making a function that accepted the source object as a parameter in the first place, a pre-extension-method practice (saving {this}, as you do in your instantiated "extension" object).
patridge
That's all extension methods are in the end. "a function that accepts the source object as a parameter in the first place". Not sure what's wrong with that or the approach laid out in my post.
kzu
+4  A: 
Mike Fielden
A: 

I created a wrapper class for the extension methods that I needed to mock.

public static class MyExtensions
{
    public static string MyExtension<T>(this T obj)
    {
        return "Hello World!";
    }
}

public interface IExtensionMethodsWrapper
{
    string MyExtension<T>(t myObj);
}

public class ExtensionMethodsWrapper
{
    public string MyExtension<T>(t myObj)
    {
        return myObj.MyExtension();
    }
}

Then you can mock the wrapper methods in your tests and code with your IOC container.

anthoro