Mock Framework: Moq
Test Framework: NUnit
I feel like there's a simple answer to this and I'm just overlooking it, but I can't for the life of me figure out why this is giving me grief.
I have two mocks here, and I'm trying to verify that the unit under test is setting one mock's property to the other mock's property, as such:
[TestFixture]
public class Testmock
{
protected Mock<IOne> mockOne;
protected Mock<ITwo> mockTwo;
protected Controller UnitUnderTest;
[SetUp]
public void Setup()
{
mockOne = new Mock<IOne>();
mockTwo = new Mock<ITwo>();
UnitUnderTest = new Controller(mockOne.Object, mockTwo.Object);
}
[Test]
public void Test1()
{
string testString = "test";
mockOne.SetupGet(o => o.Val).Returns(testString);
UnitUnderTest.CopyVal();
mockTwo.VerifySet(t => t.Val = mockOne.Object.Val);
}
}
public interface IOne
{
string Val { get; set; }
}
public interface ITwo
{
string Val { get; set; }
}
public class Controller
{
IOne one;
ITwo two;
public Controller(IOne one, ITwo two)
{
this.one = one;
this.two = two;
}
public void CopyVal()
{
two.Val = one.Val;
}
}
When I run this test, it returns an error at VerifySet that says:
Expected invocation on the mock at least once, but was never performed: t => t.Val = (String)null
But underneath that, says:
Performed invocations: ITwo.Val = "test"
So I know for certain that ITwo.Val is getting set with IOne.Val in my Controller, but I must be setting up the mock wrong here for the VerifySet. I can replace the VerifySet with the string directly, e.g.:
mockTwo.VerifySet(t => t.Val = testString);
and the test will pass. Since mockOne.Object.Val is SetupGet to return testString, I don't quite understand why I can't use mockOne.Object.Val in place of testString in the VerifySet.
I am not sure why mockOne.Object.Val returns null in the context of VerifySet. I believe it has something to do with Moq internal implementation (digging Moq sources can reveal the reason for such behavior).
However I can tell you how to change your test to make it work without using testString variable in VerifySet(). You should use It.Is(x => x == mockOne.Object.Val) instead of referring the mock property directly. Please see below:
[Test]
public void Test1()
{
string testString = "test";
mockOne.SetupGet(o => o.Val).Returns(testString);
UnitUnderTest.CopyVal();
mockTwo.VerifySet(t => t.Val = It.Is<string>(x => x == mockOne.Object.Val));
}
Hope this helps.
Related
I have looked at a number of questions here on this subject but none seem to address the issue I'm having.
I've got code that looks a bit like this...
IBaseDataCollector<MyClass> myDataCollector;
myDataCollector = new Mock<IBaseDataCollector<MyClass>>();
systemUnderTest = new Thing(myDataCollector.Object);
And in my Thing class...
var collection = myDataCollector.SomeMethod()
.SomeSecondMethod()
.GetData();
where both SomeMethod() and SomeSecondMethod() return this (ie the instance of myDataCollector)
When I run my test I get a NullReferenceException on the like where I call myDataCollector.
I tried adding this in my test setup...
myDataCollector.Setup(_=> _.SomeMethod()),Returns(myDataCollector.Object);
but that wouldn't even compile, complaining that it "Could not resolve method 'Returns(IBaseDataCollector)'"
Now, if I refactor my Thing class to read...
myDataCollector.SomeMethod();
myDataCollector.SomeSecondMethod()
var collection = myDataCollector.GetData();
my test executes properly.
If this was it, I'd just refactor my code and get on with life, but, in reality, I need to call my code inside a SelectMany call...
var collection = list.SelectMany(_=> myDataCollector.SomeMethod()
.SomeSecondMethod(_)
.GetData());
Again, I know I could replace the SelectMany with, say, a ForEach and manually populate the collection with the results of each iteration of the call to GetData() so that I can get rid of the fluent element of the calls, but this means refactoring the code just to make the tests work, which feels wrong.
How should I be calling Setup() on my Mocked objects to make my fluent calls work?
Take a look at the following test code (I've invented some details to fill in the blanks). The mocked object instance should be available as a value to return from its own methods as shown.
public class UnitTestExample
{
[Fact]
public void UnitTestExample1()
{
var myClassInterfaceMock = new Mock<IInterface<MyClass>>();
var instance = myClassInterfaceMock.Object;
var myList = new List<MyClass>()
{
new MyClass() { Attribute = 1 }
};
myClassInterfaceMock.Setup(_ => _.SomeMethod()).Returns(instance);
myClassInterfaceMock.Setup(_ => _.SomeSecondMethod()).Returns(instance);
myClassInterfaceMock.Setup(_ => _.GetData()).Returns(myList);
var myDependentClass = new MyDependentClass(instance);
var result = myDependentClass.DoTheThing();
Assert.True(result.Count.Equals(1));
}
}
public interface IInterface<T>
{
IInterface<T> SomeMethod();
IInterface<T> SomeSecondMethod();
List<T> GetData();
}
public class MyClass
{
public int Attribute { get; set; }
}
public class MyDependentClass
{
private readonly IInterface<MyClass> _test;
public MyDependentClass(IInterface<MyClass> test)
{
_test = test;
}
public List<MyClass> DoTheThing()
{
return _test.SomeMethod().SomeSecondMethod().GetData();
}
}
I am writing tests for our C# 7 application and struggle with mocking an Extension method. I am using TypeMock 8.6.10.3.
Here is a simplified example:
internal class InnerClass
{
private readonly string _description;
public InnerClass(string description)
{
_description = description;
}
public string GetDescription()
{
return _description;
}
}
internal class OuterClass
{
public void DoSthWithExtension(int someNumber)
{
var innerClass = new InnerClass("InnerClassDescription");
innerClass.Extension(someNumber);
}
}
internal static class Extensions
{
public static void Extension(this InnerClass innerClass, int someNumber)
{
var d = innerClass.GetDescription();
}
}
public void TestExtension()
{
// I want to fake the method "InnerClass.Extension()"
// which is called by "OuterClass.DoSthWithExtension()".
// I don't have access to the InnerClass instance though.
// So unfortunately I have to fake them all.
var fakedInnerClasses = Isolate.Fake.AllInstances<InnerClass>();
Isolate.WhenCalled(() => Extensions.Extension(fakedInnerClasses, 11)).WithExactArguments().DoInstead(
c =>
{
// The test doesn't go in here. The second parameter is correct,
// the first one obviously not. But what is expected as a first parameter then?
var oc2 = new OuterClass();
// Here I call InnerClass.Extension() again.
// The test should now go into the faked method underneath.
oc2.DoSthWithExtension(22);
});
Isolate.WhenCalled(() => Extensions.Extension(fakedInnerClasses, 22)).WithExactArguments().DoInstead(
c =>
{
// As above, the test code doesn't go in here.
});
// In here an instance of InnerClass is created and
// InnerClass.Extension(11) is called.
var oc1 = new OuterClass();
oc1.DoSthWithExtension(11);
}
As the this parameter of the Extension method I choose the faked instances of InnerClass. Thats what I assume is needed. But TypeMock does not bring me into the faked method. Obviously its the wrong parameter. But which one should I choose then?
Based on comments and updated question, the part that is confusing is why the other outer class is needed. The shown inner class has no dependency on the outer. Why would the mock then need to create a new outer class?
That aside, based on the docs its appears that you need to setup the extension class so that you can fake the static extension calls.
Isolate.Fake.StaticMethods(typeof(Extensions));
//...
Original answer
Do not fake the extension method in this case. You know what the extension method calls. so fake that.
public void TestExtension() {
//Arrange
string expected = "Fake result";
var fakedInnerClasses = Isolate.Fake.AllInstances<InnerClass>();
Isolate.WhenCalled(() => fakedInnerClasses.GetDescription())
.WillReturn(expected);
var subject = new OuterClass();
//Act
subject.DoSthWithExtension();
//Assert
//...
}
So now when the outer is called and the extension method invoked, it will be acting on the mock controlled by you.
I am writing a testing framework for my system, which allows users to create mocked inputs to the system. The system manipulates that input, and updates some of its members for later post processing.
In order to allow users to mock the input, I need to be able to update a mocked input's members. Furthermore, the input may not be a mock, so I would prefer a solution oblivious to the type of element received.
Simply put, I have a function which receives an object and attempts to set one of its properties:
func(object a)
a.m = 5;
Which I want to test by mocking its input a, using the Moq library. Unfortunately, my test failed, since mocked objects' members need to be set using Mock.SetUpGet, instead of standard member assignment.
What would be a good way to test such a function, without changing it?
In order to be able to mock and test it, the property must be virtual, but if that's the case you can use the SetupSet method, rather than SetupGet:
public class A
{
public virtual int m { get; set; }
}
[TestFixture]
public class Tests
{
public static void SetProperty(A a)
{
a.m = 5;
}
[Test]
public void IsThePropertySet()
{
var x = new Mock<A>();
x.SetupSet<int>(a => a.m = 5).Verifiable();
SetProperty(x.Object);
x.Verify();
}
}
Your function should have getters and setters anyway.
And a good way of testing whether your functions work is to do a small-scale test. Initialize an object and send that in to your method, seeing whether it does what you want.
public class myClass
{
public int number;
public void setNumber(int nNum)
{
number = nNum;
}
public int getNumber()
{
return number;
}
}
class Program
{
static void myMethod(myClass obj, int nNumb)
{
//obj.setNumber(nNumb);
obj.number = nNumb;
}
static void Main(string[] args)
{
myClass myObj = new myClass();
myMethod(myObj, 3);
//Console.WriteLine(myObj.getNumber());
Console.WriteLine(myObj.number);
Console.ReadLine();
}
}
}
Output: 3
Here is the code:
public interface IAccessPoint
{
int BackHaulMaximum { get; set; }
bool BackHaulMaximumReached();
void EmailNetworkProvider();
}
public class AccessPoint : IAccessPoint
{
public int BackHaulMaximum { get; set; }
public bool BackHaulMaximumReached()
{
if (BackHaulMaximum > 80)
{
EmailNetworkProvider();
return true;
}
return false;
}
public void EmailNetworkProvider()
{
}
}
//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var apMock = MockRepository.GenerateMock<IAccessPoint>();
apMock.Stub(x => x.BackHaulMaximum).Return(81);
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
apMock.AssertWasCalled(x => x.EmailNetworkProvider());
}
You shouldn't be mocking the class that you are testing. You should only be mocking the classes that class under test depends on. Something like this:
public interface IAccessPoint
{
int BackHaulMaximum { get; set; }
bool BackHaulMaximumReached();
void EmailNetworkProvider();
}
public class AccessPoint : IAccessPoint
{
private IMailProvider Mailer { get; set; }
public AccessPoint( IMailProvider provider )
{
this.Mailer = provider ?? new DefaultMailProvider();
}
public int BackHaulMaximum { get; set; }
public bool BackHaulMaximumReached()
{
if (BackHaulMaximum > 80)
{
EmailNetworkProvider();
return true;
}
return false;
}
public void EmailNetworkProvider()
{
this.Mailer.SendMail(...);
}
}
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var mailerMock = MockRepository.GenerateMock<IMailProvider>();
mailerMock .Expect( m => m.SendMail( ... specify argument matches ... ) );
var accessPoint = new AccessPoint( mailerMock );
accessPoint.BackHaulMaximum = 81;
Assert.IsTrue( accessPoint.BackHaulMaximumReached() );
mailerMock.VerifyAllExpectations();
}
I agree with tvanfosson's answer. 99% (maybe 100%) of the time, you won't want a mock for your SUT.
However the reason it is failing is because your call:
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
is not going to result in the actual method BackHaulMaximumReached() being called! It's going to call the mock's method.
Edit
If it wasn't clear, that means that BackHaulMaximumReached() will (I think) return the default value for its return type, which is "false" in the case of bools. So you need to stub out that method to return true to get the Assert.AreEqual to to pass (which is not a good test as I said).
Your next assertion will then fail, as EmailNetworkProvider() will never get called (again, because you are calling the mock's methods, not the actual SUT's methods).
I would change the code as follows:
//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var mockRepo = new MockRepository();
var apMock = mockRepo.PartialMock<AccessPoint>();
using (mockRepo.Record())
{
Expect.Call(apMock.EmailNetworkProvider).Repeat.Once();
}
using (mockRepo.Playback())
{
apMock.BackHaulMaximum = 81;
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
}
mockRepo.VerifyAll();
}
What you're expecting is that given the input to the class, when you call a method, another method that induces some unwanted side effects is also called. You want to mock the side-effect-inducing behavior, but you want to exercise the rest of the actual logic.
The solution is a PartialMock. It allows the mocking behavior to be applied to only the members of the mocked class that you specify. You can use it in several syntaxes, but the safest, most reliable method is to record and playback expectations rather than call the Expects() method on the mock itself.
We are using it here to expect a call on our method that we want to mock; expecting the call will cause the actual method not to be called. Then, the class is exercised, and the logic of the actual class is used (hence the assertion in our test succeeds), but when the call to our expected method is reached, what is actually called is the mocked method that updates some internal counters. Then, VerifyAll() asserts that all expectations happened according to the settings prescribed.
How can I test that a particular method was called with the right parameters as a result of a test? I am using NUnit.
The method doesn't return anything. it just writes on a file. I am using a mock object for System.IO.File. So I want to test that the function was called or not.
More context is needed. So I'll put one here adding Moq to the mix:
pubilc class Calc {
public int DoubleIt(string a) {
return ToInt(a)*2;
}
public virtual int ToInt(string s) {
return int.Parse(s);
}
}
// The test:
var mock = new Mock<Calc>();
string parameterPassed = null;
mock.Setup(c => x.ToInt(It.Is.Any<int>())).Returns(3).Callback(s => parameterPassed = s);
mock.Object.DoubleIt("3");
Assert.AreEqual("3", parameterPassed);
You have to use some mocking framework, such as Typemock or Rhino Mocks, or NMocks2.
NUnit also has a Nunit.Mock, but it is not well-known.
The syntax for moq can be found here:
var mock = new Mock<ILoveThisFramework>();
// WOW! No record/reply weirdness?! :)
mock.Setup(framework => framework.DownloadExists("2.0.0.0"))
.Returns(true)
.AtMostOnce();
// Hand mock.Object as a collaborator and exercise it,
// like calling methods on it...
ILoveThisFramework lovable = mock.Object;
bool download = lovable.DownloadExists("2.0.0.0");
// Verify that the given method was indeed called with the expected value
mock.Verify(framework => framework.DownloadExists("2.0.0.0"));
Also, note that you can only mock interface, so if your object from System.IO.File doesn't have an interface, then probably you can't do. You have to wrap your call to System.IO.File inside your own custom class for the job.
By using a mock for an interface.
Say you have your class ImplClass which uses the interface Finder and you want to make sure the Search function gets called with the argument "hello";
so we have:
public interface Finder
{
public string Search(string arg);
}
and
public class ImplClass
{
public ImplClass(Finder finder)
{
...
}
public void doStuff();
}
Then you can write a mock for your test code
private class FinderMock : Finder
{
public int numTimesCalled = 0;
string expected;
public FinderMock(string expected)
{
this.expected = expected;
}
public string Search(string arg)
{
numTimesCalled++;
Assert.AreEqual(expected, arg);
}
}
then the test code:
FinderMock mock = new FinderMock("hello");
ImplClass impl = new ImplClass(mock);
impl.doStuff();
Assert.AreEqual(1, mock.numTimesCalled);
In Rhino Mocks where is a method called AssertWasCalled
Here is a way to use it
var mailDeliveryManager = MockRepository.GenerateMock<IMailDeliveryManager>();
var mailHandler = new PlannedSending.Business.Handlers.MailHandler(mailDeliveryManager);
mailHandler.NotifyPrinting(User, Info);
mailDeliveryManager.AssertWasCalled(x => x.SendMailMessage(null, null, null), o => o.IgnoreArguments());