I have a preexisting Interface...
public interface ISomeInterface
{
void SomeMethod();
}
and I've extended this intreface using a mixin...
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
I have a class thats calling this which I want to test...
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
and a test where I'd like to mock the interface and verify the call to the extension method...
[Test]
public void Main_BasicCall_CallsAnotherMethod()
{
// Arrange
var someInterfaceMock = new Mock<ISomeInterface>();
someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable();
var caller = new Caller(someInterfaceMock.Object);
// Act
caller.Main();
// Assert
someInterfaceMock.Verify();
}
Running this test however generates an exception...
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
My question is, is there a nice way to mock out the mixin call?
I have used a Wrapper to get around this problem. Create a wrapper object and pass your mocked method.
See Mocking Static Methods for Unit Testing by Paul Irwin, it has nice examples.
You can't "directly" mock static method (hence extension method) with mocking framework. You can try Moles (http://research.microsoft.com/en-us/projects/pex/downloads.aspx), a free tool from Microsoft that implements a different approach.
Here is the description of the tool:
Moles is a lightweight framework for test stubs and detours in .NET that is based on delegates.
Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types.
You can use Moles with any testing framework (it's independent about that).
I found that I had to discover the inside of the extension method I was trying to mock the input for, and mock what was going on inside the extension.
I viewed using an extension as adding code directly to your method. This meant I needed to mock what happens inside the extension rather than the extension itself.
I like to use the wrapper (adapter pattern) when I am wrapping the object itself. I'm not sure I'd use that for wrapping an extension method, which is not part of the object.
I use an internal Lazy Injectable Property of either type Action, Func, Predicate, or delegate and allow for injecting (swapping out) the method during a unit test.
internal Func<IMyObject, string, object> DoWorkMethod
{
[ExcludeFromCodeCoverage]
get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); }
set { _DoWorkMethod = value; }
} private Func<IMyObject, string, object> _DoWorkMethod;
Then you call the Func instead of the actual method.
public object SomeFunction()
{
var val = "doesn't matter for this example";
return DoWorkMethod.Invoke(MyObjectProperty, val);
}
For a more complete example, check out http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
If you just want to make sure that the extension method was invoked, and you aren't trying to setup a return value, then you can check the Invocations property on the mocked object.
Like this:
var invocationsCount = mockedObject.Invocations.Count;
invocationsCount.Should().BeGreaterThan(0);
Reason why it is not possible to mock an extension method is already given in good answers. I am just trying to give another possible solution with this answer: Extract a protected, virtual method with the call to the extension method and create a setup for this method in the test class/method by using a proxy.
public class Foo
{
public void Method()
=> CallToStaticMethod();
protected virtual void CallToStaticMethod()
=> StaticClass.StaticMethod();
}
and test
[TestMethod]
public void MyTestMethod()
{
var expected = new Exception("container exception");
var proxy = new Mock<Foo>();
proxy.Protected().Setup("CallToStaticMethod").Throws(expected);
var actual = Assert.ThrowsException<Exception>(() => proxy.Object.Foo());
Assert.AreEqual(expected, actual);
}
In my case extension method is a method around some public method of my class. So I checked call of that internal method. That approach is similar to Alvis answer (above).
So if you are using Moq, and want to mock the result of an Extension method, then you can use SetupReturnsDefault<ReturnTypeOfExtensionMethod>(new ConcreteInstanceToReturn()) on the instance of the mock class that has the extension method you are trying to mock.
It is not perfect, but for unit testing purposes it works well.
Related
Recently, I've begun to use Moq to unit test. I use Moq to mock out classes that I don't need to test.
How do you typically deal with static methods?
public void foo(string filePath)
{
File f = StaticClass.GetFile(filePath);
}
How could this static method, StaticClass.GetFile() get mocked?
P.S. I'd appreciate any reading materials you recommend on Moq and Unit Testing.
#Pure.Krome: good response but I will add a few details
#Kevin: You have to choose a solution depending on the changes that you can bring to the code.
If you can change it, some dependency injection make the code more testable.
If you can't, you need a good isolation.
With free mocking framework (Moq, RhinoMocks, NMock...) you can only mock delegates, interfaces and virtual methods. So, for static, sealed and non-virtual methods you have 3 solutions:
TypeMock Isolator (can mock everything but it's expensive)
JustMock of Telerik (new comer, less expensive but still not
free)
Moles of Microsoft (the only free solution for isolation)
I recommend Moles, because it's free, efficient and use lambda expressions like Moq. Just one important detail: Moles provide stubs, not mocks. So you may still use Moq for interface and delegates ;)
Mock: a class that implements an interface and allows the ability to dynamically set the values to return/exceptions to throw from particular methods and provides the ability to check if particular methods have been called/not called.
Stub: Like a mock class, except that it doesn't provide the ability to verify that methods have been called/not called.
Mocking frameworks like Moq or Rhinomocks can only create mock instances of objects, this means mocking static methods is not possible.
You can also search Google for more info.
Also, there's a few questions previously asked on StackOverflow here, here and here.
There is a possibility in .NET excluding MOQ and any other mocking library. You have to right click on solution explorer on assembly containing static method you want to mock and choose Add Fakes Assembly. Next you can freely mock that assembly static methods.
Assume that you want to mock System.DateTime.Now static method. Do this for instance this way:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => new DateTime(1837, 1, 1);
Assert.AreEqual(DateTime.Now.Year, 1837);
}
You have similar property for each static property and method.
You can achieve this with Pose library available from nuget. It allows you to mock, among other things, static methods. In your test method write this:
Shim shim = Shim.Replace(() => StaticClass.GetFile(Is.A<string>()))
.With((string name) => /*Here return your mocked value for test*/);
var sut = new Service();
PoseContext.Isolate(() =>
result = sut.foo("filename") /*Here the foo will take your mocked implementation of GetFile*/, shim);
For further reading refer here https://medium.com/#tonerdo/unit-testing-datetime-now-in-c-without-using-interfaces-978d372478e8
I liked Pose but couldn't get it to stop throwing InvalidProgramException which appears to be a known issue. Now I'm using Smocks like this:
Smock.Run(context =>
{
context.Setup(() => DateTime.Now).Returns(new DateTime(2000, 1, 1));
// Outputs "2000"
Console.WriteLine(DateTime.Now.Year);
});
I've been playing around with a concept of refactoring the static methods to invoke a delegate which you can externally set for testing purposes.
This would not use any testing framework and would be a completely bespoke solution however the refactor will not influence the signature of your caller and so it would be a relatively safe.
For this to work, you would need to have access to the static method, so it wouldn't work for any external libraries such as System.DateTime.
Heres an example I've been playing with where I've created a couple of static methods, one with a return type that takes in two parameters and one generic which has no return type.
The main static class:
public static class LegacyStaticClass
{
// A static constructor sets up all the delegates so production keeps working as usual
static LegacyStaticClass()
{
ResetDelegates();
}
public static void ResetDelegates()
{
// All the logic that used to be in the body of the static method goes into the delegates instead.
ThrowMeDelegate = input => throw input;
SumDelegate = (a, b) => a + b;
}
public static Action<Exception> ThrowMeDelegate;
public static Func<int, int, int> SumDelegate;
public static void ThrowMe<TException>() where TException : Exception, new()
=> ThrowMeDelegate(new TException());
public static int Sum(int a, int b)
=> SumDelegate(a, b);
}
The Unit Tests (xUnit and Shouldly)
public class Class1Tests : IDisposable
{
[Fact]
public void ThrowMe_NoMocking_Throws()
{
Should.Throw<Exception>(() => LegacyStaticClass.ThrowMe<Exception>());
}
[Fact]
public void ThrowMe_EmptyMocking_DoesNotThrow()
{
LegacyStaticClass.ThrowMeDelegate = input => { };
LegacyStaticClass.ThrowMe<Exception>();
true.ShouldBeTrue();
}
[Fact]
public void Sum_NoMocking_AddsValues()
{
LegacyStaticClass.Sum(5, 6).ShouldBe(11);
}
[Fact]
public void Sum_MockingReturnValue_ReturnsMockedValue()
{
LegacyStaticClass.SumDelegate = (a, b) => 6;
LegacyStaticClass.Sum(5, 6).ShouldBe(6);
}
public void Dispose()
{
LegacyStaticClass.ResetDelegates();
}
}
Using Microsoft Fakes:
Add the fakes assembly, then if you have this static method...
//code under test
public static class MyClass {
public static int MyMethod() {
...
}
}
... you can mock it like this:
// unit test code
using (ShimsContext.Create())
{
ShimMyClass.MyMethod = () => 5;
}
Source: https://learn.microsoft.com/en-us/visualstudio/test/using-shims-to-isolate-your-application-from-other-assemblies-for-unit-testing?view=vs-2019#static-methods
i'm trying to use Moq to mock an extension method from the IDataAccessAdapter interface from LLBLGen. Here is FetchQueryAsync the extension method.
Doing so gave me the error that i can't Mock static extension methods. However there is no way i can change the code. So i tried creating a wrapper class, yet i had no success doing that either because i do not know how to apply it.
In the method Fetch, i want FetchQueryAsync to return an object i specified during the test and not actually execute the query.
public class QueryHandler
{
private IDataAccessAdapterProvider dataAccessAdapterProvider;
public QueryHandler(IDataAccessAdapterProvider provider)
{
this.dataAccessAdapterProvider = provider;
}
private async Task<T> Fetch(DynamicQuery<T> query)
{
using (IDataAccessAdapter adapter = dataAccessAdapterProvider.Provide()
{
result = await adapter.FetchQueryAsync(query)
}
}
}
public class DataAccessAdapterProvider : IDataAccessAdapterProvider
{
public IDataAccessAdapter Provide()
{
var adapter = new DataAccessAdapter();
return adapter;
}
}
So in my Unit Test i have this:
List<int> il = new List<int>();
Mock<IDataAccessAdapterProvider> mock = new Mock<IDataAccessAdapterProvider>();
mock.Setup(m => m.Provide()
.FetchQueryAsync<int>(It.IsAny<DynamicQuery<int>>()))
.ReturnsAsync(il);
This won't work however because it's not supported.
So i tried wrapping the method as such.
interface IWrap
{
Task<List<TElement>> FetchQueryAsync<TElement>(IDataAccessAdapter adapter, DynamicQuery<TElement> query);
}
public class Wrap : IWrap
{
public async Task<List<TElement>> FetchQueryAsync<TElement>(IDataAccessAdapter adapter, DynamicQuery<TElement> query)
{
return await adapter.FetchQueryAsync(query);
}
}
How do i apply this wrapper with Moq to mock the interface?
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.
I have the following class:
public class MyClass : IMyClass
{
public string MyFunc(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new Exception("Blank Name");
}
return name;
}
public double MyFuncWrapper(string name)
{
var value = MyFunc(name);
return value;
}
In trying to test it, I was under the impression that NSubstitute's ForPartsOf effectively subclassed my class and replaced the flagged methods; so I did this:
[Fact]
public void TestMyFuncWrapper()
{
// Arrange
var myClass = Substitute.ForPartsOf<MyClass>();
myClass.MyFunc(Arg.Any<string>()).Returns("Test");
// Act
var result = myClass.MyFuncWrapper("");
// Assert
Assert.Equal("Test", result);
}
However, I get the exception raised from, what I understood to be, my substituted method. Oddly, it appears that the following line:
myClass.MyFunc(Arg.Any<string>()).Returns("Test");
Is actually calling the concrete function immediately. Looking here, it appeared that a construct like this may solve the problem (although it does use the phrase "playing it safe" which sounds quite vague):
myClass.When(a => a.MyFunc(Arg.Any<string>())).DoNotCallBase();
However, calling this actually invokes MyFunc immediately in the same way. Clearly I'd misunderstood the ForPartsOf method; my question is: can I do what I'm attempting using NSubstitute, or do I need to resort to manually subclassing MyClass?
This is by design for NSubstitute (and for most mocking frameworks).
The docs state:
For starters, NSubstitute can only work with virtual members of the
class, so any non-virtual code in the class will actually execute!
Thus, you need to add virtual to the function declarations you plan to mock.
Or (as per the docs):
If possible, stick to substituting interfaces.
I have the following classes:
public class HelperClass
{
HandleFunction<T>(Func<T> func)
{
// Custom logic here
func.Invoke();
// Custom logic here
}
// The class i want to test
public class MainClass
{
public readonly HelperClass _helper;
// Ctor
MainClass(HelperClass helper)
{
_helper = helper;
}
public void Foo()
{
// Use the handle method
_helper.HandleFunction(() =>
{
// Foo logic here:
Action1();
Action2(); //etc..
}
}
}
I want to test MainClass only. I a using RhinoMocks to mock HelperClass in my tests.
The problem is, while I am not interested in testing the HandleFunction() method I am interested in checking Action1, Action2 and other actions that were sent to HandleFunction() when called..
How can I mock the HandleFunction() method and while avoiding it's inner logic, invoke the code that was sent to it as a parameter?
Because your unit under test most probably requires the delegate to be called before proceeding, you need to call it from the mock. There is still a difference between calling the real implementation of the helper class and the mock implementation. The mock does not include this "custom logic". (If you need that, don't mock it!)
IHelperClass helperMock = MockRepository.GenerateMock<IHelperClass>();
helperMock
.Stub(x => x.HandleFunction<int>())
.WhenCalled(call =>
{
var handler = (Func<int>)call.Argument[0];
handler.Invoke();
});
// create unit under test, inject mock
unitUnderTest.Foo();
In addition to Stefan's answer I'd like to show quite another way to define stub which invokes passed argument:
handler
.Stub(h => h.HandleFunction(Arg<Func<int>>.Is.Anything))
.Do((Action<Func<int>>)(func => func()));
Please read more about Do() handler here and here.
I have a preexisting Interface...
public interface ISomeInterface
{
void SomeMethod();
}
and I've extended this intreface using a mixin...
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
I have a class thats calling this which I want to test...
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
and a test where I'd like to mock the interface and verify the call to the extension method...
[Test]
public void Main_BasicCall_CallsAnotherMethod()
{
// Arrange
var someInterfaceMock = new Mock<ISomeInterface>();
someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable();
var caller = new Caller(someInterfaceMock.Object);
// Act
caller.Main();
// Assert
someInterfaceMock.Verify();
}
Running this test however generates an exception...
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
My question is, is there a nice way to mock out the mixin call?
I have used a Wrapper to get around this problem. Create a wrapper object and pass your mocked method.
See Mocking Static Methods for Unit Testing by Paul Irwin, it has nice examples.
You can't "directly" mock static method (hence extension method) with mocking framework. You can try Moles (http://research.microsoft.com/en-us/projects/pex/downloads.aspx), a free tool from Microsoft that implements a different approach.
Here is the description of the tool:
Moles is a lightweight framework for test stubs and detours in .NET that is based on delegates.
Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types.
You can use Moles with any testing framework (it's independent about that).
I found that I had to discover the inside of the extension method I was trying to mock the input for, and mock what was going on inside the extension.
I viewed using an extension as adding code directly to your method. This meant I needed to mock what happens inside the extension rather than the extension itself.
If you just want to make sure that the extension method was invoked, and you aren't trying to setup a return value, then you can check the Invocations property on the mocked object.
Like this:
var invocationsCount = mockedObject.Invocations.Count;
invocationsCount.Should().BeGreaterThan(0);
I like to use the wrapper (adapter pattern) when I am wrapping the object itself. I'm not sure I'd use that for wrapping an extension method, which is not part of the object.
I use an internal Lazy Injectable Property of either type Action, Func, Predicate, or delegate and allow for injecting (swapping out) the method during a unit test.
internal Func<IMyObject, string, object> DoWorkMethod
{
[ExcludeFromCodeCoverage]
get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); }
set { _DoWorkMethod = value; }
} private Func<IMyObject, string, object> _DoWorkMethod;
Then you call the Func instead of the actual method.
public object SomeFunction()
{
var val = "doesn't matter for this example";
return DoWorkMethod.Invoke(MyObjectProperty, val);
}
For a more complete example, check out http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
Reason why it is not possible to mock an extension method is already given in good answers. I am just trying to give another possible solution with this answer: Extract a protected, virtual method with the call to the extension method and create a setup for this method in the test class/method by using a proxy.
public class Foo
{
public void Method()
=> CallToStaticMethod();
protected virtual void CallToStaticMethod()
=> StaticClass.StaticMethod();
}
and test
[TestMethod]
public void MyTestMethod()
{
var expected = new Exception("container exception");
var proxy = new Mock<Foo>();
proxy.Protected().Setup("CallToStaticMethod").Throws(expected);
var actual = Assert.ThrowsException<Exception>(() => proxy.Object.Foo());
Assert.AreEqual(expected, actual);
}
In my case extension method is a method around some public method of my class. So I checked call of that internal method. That approach is similar to Alvis answer (above).
So if you are using Moq, and want to mock the result of an Extension method, then you can use SetupReturnsDefault<ReturnTypeOfExtensionMethod>(new ConcreteInstanceToReturn()) on the instance of the mock class that has the extension method you are trying to mock.
It is not perfect, but for unit testing purposes it works well.