Mocking a method that takes a mocked parameter object in C# - c#

The to be tested method
public string GetPopulatedField(string input)
{
IParameterCollection sqlParams = CreateParameterCollection();
sqlParams.Add("param", input);
string recordCollection = DataAccess.ExecuteSelect(SQL, ref sqlParams);
return recordCollection ;
}
The test method
public void Test()
{
// Mocking one of the dependencies used by the ExecuteSelect
MockHelper.CreateAndRegisterMock<IParameterCollection>();
Mock<Access> mock = new Mock<Access>();
//mocking the ExecuteSelect Method that takes a string and and IParameterCollection
mock.Setup(t => t.ExecuteSelect(It.IsAny<string>(),ref It.Ref<IParameterCollection>.IsAny)).Returns("123");
//The execute Select is called from the GetPopulatedField method
var x= MockHelper.CreateAndRegisterMock<PopulateField>("Container");
Assert.AreEqual("123", x.Object.GetPopulatedField("value"));
}
The issue is when ExecuteSelect is called from GetPopulateField it is using the Mock object and not the actual IParameterCollection, so what is the correct way to Mock the ExecuteSelect properly?
ref It.Ref<IParameterCollection>.IsAny I believe this should be changed to reflect the mocked one.

In a unit test, it is important to only test a unit, a small portion of code. The smaller the unit,
the easier the reason can be found if a failure occurs.
the faster the tests can be run.
In order to reduce the code to the relevant unit, two aspects are important:
you want to test the real code of the unit as it would be used in the program flow - hence you create a real instance of the class you want to test, not a mock.
you do not want to test code that the unit depends on - therefore
you structure your code in a way that you can replace dependencies with mocks and
you create mocks for the dependencies when testing.
With that in mind, you could change your PopulateField class like this:
public class PopulateField
{
private readonly IDataAccess _dataAccess;
public PopulateField(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public string GetPopulatedField(string input)
{
IParameterCollection sqlParams = CreateParameterCollection();
sqlParams.Add("param", input);
string recordCollection = _dataAccess.ExecuteSelect(SQL, ref sqlParams);
return recordCollection;
}
// ...
}
With an instance of type IDataAccess injected into the constructor and used in the GetPopulatedFields method, you can easily replace it with a mock in the tests:
public void Test()
{
// Create a mock for the data access
Mock<IDataAccess> mockDataAccess = new Mock<IDataAccess>();
//mocking the ExecuteSelect Method that takes a string and and IParameterCollection
mockDataAccess.Setup(t => t.ExecuteSelect(It.IsAny<string>(),ref It.Ref<IParameterCollection>.IsAny())).Returns("123");
// Create an instance of PopulateFields so the tests run on real code
var pf = new PopulateFields(mockDataAccess.Object);
var actual = pf.GetPopulatedFields("input");
Assert.AreEqual("123", actual);
}
Please note that the creation of the IParameterCollection happens in a method of PopulateFields that you cannot replace with this behavior. There are two ways to go about this:
If it is important to also mock the instantiation of the ParameterCollection, you need to create a factory interface that contains a method that returns the IParameterCollection instance. Along with IDataAccess an instance implementing this interface is also injected into the constructor of PopulateFields so you can replace it with a mock when testing.
If you only want to validate that the correct parameters are set when GetPopulatedFields is called, you can add a validation to the setup. Unfortunately, for It.Ref<T> there is only a IsAny and no Is method that allows deciding whether the parameters match, so we solve it with a callback:
mock.Setup(t => t.ExecuteSelect(It.IsAny<string>(),ref It.Ref<IParameterCollection>.IsAny)).Callback((string s, ref IParameterCollection params) => {
if (!params.Contains("param")) // Adjust conditions to IParameterCollection
throw new ApplicationException("Parameter was not added");
}.Returns("123");

Related

How to mock IMemoryCache instance methods using Moq that are being hidden by extension methods in C#? [duplicate]

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.

NSubstitute ordered testing (Recived.InOrder) with return values for called methods results in CouldNotSetReturnDueToMissingInfoAboutLastCallException

I used to write my tests with RhinoMocks and have switched to NSubstitute.
Now I have a problem concerning ordered test.
Lets say I have three small classes like
public interface IProvider
{
int GetData();
}
public class Provider : IProvider
{
public int GetData()
{
return 3;
}
}
public interface ICalculator
{
int Calculate(int data);
}
public class Calculator : ICalculator
{
public int Calculate(int data)
{
if (data < 3)
{
return data;
}
return data * 2;
}
}
public class Operator
{
public void Operate(IProvider provider, ICalculator calculator)
{
int version = provider.GetData();
this.Result = calculator.Calculate(version);
}
public int Result
{
get;
private set;
}
}
When I write an ordered test using RhinoMocks, I can define the behaviour for the mocked classes like this:
[Test]
public void RhinoMockOrderedTest()
{
var mockRepository = new MockRepository();
var provider = mockRepository.DynamicMock<IProvider>();
var calculator = mockRepository.DynamicMock<ICalculator>();
using (mockRepository.Ordered())
{
provider.Expect(p => p.GetData()).Return(4);
calculator.Expect(c => c.Calculate(4)).Return(9);
}
mockRepository.ReplayAll();
var op = new Operator();
op.Operate(provider, calculator);
mockRepository.VerifyAll();
Assert.That(op.Result, Is.EqualTo(9));
}
Now I was trying to write an ordered test like the one above using NSubstitute, where I was also trying to check the call order and using defined return values:
[Test]
public void NSubstituteOrderedTest()
{
var provider = Substitute.For<IProvider>();
var calculator = Substitute.For<ICalculator>();
var op = new Operator();
op.Operate(provider, calculator);
Received.InOrder(() =>
{
provider.GetData().Returns(4);
calculator.Calculate(4).Returns(9);
});
Assert.That(op.Result, Is.EqualTo(9));
}
Unfortunalely this does not work. It seems to me, when I try to use .Returns for a methon inside of the Received.InOrder - Action, it will alwys fail like this:
NSubstitute.Exceptions.CouldNotSetReturnDueToMissingInfoAboutLastCallException
: Could not find information about the last call to return from.
Make sure you called Returns() after calling your substitute (for
example: mySub.SomeMethod().Returns(value)), and that you are not
configuring other substitutes within Returns() (for example, avoid
this: mySub.SomeMethod().Returns(ConfigOtherSub())).
If you substituted for a class rather than an interface, check that
the call to your substitute was on a virtual/abstract member. Return
values cannot be configured for non-virtual/non-abstract members.
Correct use: mySub.SomeMethod().Returns(returnValue);
Potentially problematic use:
mySub.SomeMethod().Returns(ConfigOtherSub()); Instead try: var
returnValue = ConfigOtherSub();
mySub.SomeMethod().Returns(returnValue);
How can I write this test using NSubstitute ?
Thanks,
Nico
NSubstitute works differently to Rhino Mocks here -- it only supports Arrange-Act-Assert (AAA) style tests. This means we need to stub out calls we're interested in (arrange), run the code we want to test (act), then assert the results are as expected (assert).
Received.InOrder is only for assertions, and works like NSubstitute's Received() method for each call. Returns arranges for a call to return a particular result. NSubstitute does not allow us to mix the two. We can't do sub.Received().Calculate().Returns(42), and it does not make sense to in AAA as there is little point in stubbing a return value after asserting we have already acted on the subject being tested and received all required calls.
Here is a passing version of the test from the question that separates the stubbing/arranging from the assertions:
[Test]
public void NSubstituteOrderedTest() {
// Arrange
var provider = Substitute.For<IProvider>();
var calculator = Substitute.For<ICalculator>();
provider.GetData().Returns(4);
calculator.Calculate(4).Returns(9);
// Act
var op = new Operator();
op.Operate(provider, calculator);
// Assert
Received.InOrder(() =>
{
provider.GetData();
calculator.Calculate(4);
});
Assert.That(op.Result, Is.EqualTo(9));
}
Aside: I know this is a simplified example, but I think it's worth noting that in many cases we can get away without testing the call ordering. For this simple case, we know GetData() is called first, as its value is passed to Calculate(), so the order is enforced via the data dependency. If the end result is correct, we know the call chain was correct. For more complicated cases we can use types for this (Connect() returns ConnectedDb, then Query(ConnectedDb db) ensures Connect() was called first.
Relying on knowledge of the implementation details of the code being tested (such as call ordering) can lead to brittle tests (i.e. they fail with small changes that should not affect the overall result), so it is best to avoid this where possible.
However, even with this disclaimer, it is sometimes useful to assert call order instead, so I hope this answer clears up this NSubstitute feature for you. :)

Unit test factory method for object with dependencies

I'm new in unit testing.
Its suggested to use Factory method to create instance of class under test for maintainability reasons.
Like:
public class StringCalculatorTests
{
[Fact]
public void Add_EmptyString_ReturnZero()
{
var calculator = CreateCalculator();
int result = calculator.Add("");
result.Should().Be(0);
}
private static StringCalculator CreateCalculator()
{
//Some difficult object creation
var logger = Substitute.For<ILogger>();
var calculator = new StringCalculator(logger);
calculator.Initialize();
return calculator;
}
}
Everything nice: if API changes - i will change StringCalculator creation only in one place, not in every tests.
But what if i need to change a return value for some method of ILogger. Or I will use ILogger not as stub but as a mock:
[Fact]
public void Add_EmptyString_LogAboutEmptyInput()
{
var loggerMock = Substitute.For<ILogger>();
var calculator = new StringCalculator(loggerMock);
calculator.Initialize();
calculator.Add("");
logger.Received("Empty input.");
}
Now i can't use factory method, and if there are changes in API - i should go through my tests to change it.
I thought about property injection - but it may be not good local default for ILogger for example.
(i know - we usually have good default for logger, but it can be some another dependency)
I thought about optional parameters for factory method. But it seems to have logic. It's very simple but still logic.
Is there any good approach to solve this? Or it's good enough and it's a common situation to create instance just in class when we need it?
You can overload your factory method to accept a mock logger.
private static StringCalculator CreateCalculator(ILogger logger)
{
var calculator = new StringCalculator(logger);
calculator.Initialize();
return calculator;
}
Then you can create your mock logger in the test (possibly a separate factory method for the logger if the same mocking is used in multiple tests)
[Fact]
public void Add_EmptyString_LogAboutEmptyInput()
{
var loggerMock = //whatever code you need to set up your mock
var calculator = CreateCalculator(loggerMock);
calculator.Add("");
logger.Received("Empty input.");
}

RhinoMocks AssertWasCalled on mocked object's method that needs to have an object returned?

Using RhinoMocks, I have a catch-22 situation: I want to verify that a method is called, but this method needs to have an object returned on it because the returned object is acted on in the next line. In other words, mocking on the interface just returns a null value, but not mocking it up doesn't give me any way to verify that the method was called apart from some kind of integration test.
Therefore, looking at the contrived sample below that I threw together, is there a way to do what I'm wanting? I thought there might be a way to set the AssertWasCalled method to actually return something as when stubbing a method, but...thanks for any pointers (especially if it's simply a design flaw that should be addressed instead).
public class SomeClass
{
private readonly ISomeMapper _someMapper;
[Inject]
public Test(ISomeMapper someMapper)
{
_someMapper = someMapper;
}
public SomeReturnType SomeMethod(IEnumerable<ISomethingToMap> somethings)
{
//foreach over somethings and do something based on various properties for each
MappedSomething mappedSomething = _someMapper.Map(something); // AssertWasCalled here
mappedSomething.SomeProperty = somethingFromSomewhere; // Which gets a null reference exception here (understandably) if _someMapper is mocked
//end foreach after more stuff
}
}
///...
[Test]
public void the_mapper_should_be_called()
{
//If mock or stub, then can AssertWasCalled, but then only null object returned.
// If don't mock, then cannot assert whether was called.
var mapper = MockRepository.GenerateStub<ISomeMapper>();
var somethingToMap = _someListOfSomethings[0];
var sut = new SomeClass(mapper);
sut.SomeMethod(_someListOfSomethings);
mapper.AssertWasCalled(x => x.Map(somethingToMap));
}
You can set an expectation on the mock object that the method was called along with the return value:
MappedSomething fakeMappedSomething = //whatever
mapper.Expect(m => m.Map(something)).Return(fakeMappedSomething);
...
sut.SomeMethod(_someListOfSomethings);
Then verify the expectations at the end of the test.

How to assert a private method on concrete class is called (TypeMock/NMock/etc..)?

I am trying to write a unit test for the 'IsUnique' function in the class below that looks like this:
class Foo
{
public bool IsUnique(params...)
{
ValidateStuffExists(params);
return CheckUniqueness(params);
}
private void ValidateStuffExists(params)
{
//does some validation
}
private bool CheckUniqueness(params)
{
//does logic to determine if its unique per params
return result;
}
}
The only thing I want to test here is that ValidateStuffExists and CheckUniqueness is called and passed the arguments. That's all this function does so it's all I'm going to test (I'll bend the 'test public behavior only' psuedo-rule and test the private methods here, because its either have one big complicated method/tests or testing 2 private methods).
I am open to any mocking library. I use NMock and didn't think it was up for the Task - so I downloaded TypeMock as I've done reading and heard that this was the best and that it could mock out even concrete classes / non interface method calls...
I'm doing something like this in my test and it throws exception at the 'Isolate.WhenCalled' line:
CrmEntityUniqueValidator_Accessor target = new CrmEntityUniqueValidator_Accessor(); // TODO: Initialize to an appropriate value
DynamicEntity entity = null; // TODO: Initialize to an appropriate value
string[] propertyNames = null; // TODO: Initialize to an appropriate value
bool tru = true;
Isolate.WhenCalled(() => target.CheckUniqueness(entity, propertyNames, null, null)).WillReturn(tru);
target.ValidatePropertiesExist(entity, propertyNames);
Isolate.Verify.WasCalledWithArguments(() => target.ValidatePropertiesExist(entity, propertyNames));
Isolate.Verify.WasCalledWithArguments(() => target.CheckUniqueness(entity, propertyNames, null, null));
This throws an exception like "*** WhenCalled does not support using a method call as an argument."
Even though I'm able to do the same thing with a CLR class - I can mock out DateTime.Now doing this (code works):
DateTime endOfWorld = new DateTime(2012, 12, 23);
Isolate.WhenCalled(() => DateTime.Now).WillReturn(endOfWorld);
DateTime dt = DateTime.Now;
Assert.AreEqual(dt, endOfWorld);
Anyone have any advice here? Do I have to split these 2 methods into a seperate class and make an interface is the only way? or complicate my method/tests??? There must be something I'm missing here... Thanks much for any help in advance.
EDIT: I guess I'm trying to mock out the 2 private methods in the class for the one unit test. How could I do this without having to split out those 2 methods into a seperate class / interface?
try
Isolate.NonPublic.WhenCalled(object,"nonpublic method").IgnoreCall
or Isolate.Verify.NonPublic.WasCalled(object,"method"..
RhinoMocks has the AssertWasCalled method which may serve the purpose of guaranteeing that a method calls another method... but I'm not sure you can do that on a private function of the same class you are unit testing. I think you could only do that if the two methods you wanted to stub were in another dependency class that was injected.

Categories

Resources