How to mock a method inside the same class being tested? - c#

I am creating some unit tests for a method ValidateObject in a service ObjectService. The ValidateObject method calls another method ValidateObjectPropertyB. I want to mock the calls to the last method.
The ObjectService and relevant method look like this:
public class ObjectService : IObjectService
{
public bool ValidateObject(object objectToValidate)
{
return
!String.IsNullOrEmpty(objectToValidate.PropertyA) &&
ValidateObjectPropertyB(objectToValidate.PropertyB, currentUserId);
}
public bool ValidateObjectPropertyB(long propertyB, long userId)
{
return validationResult;
}
}
Right now my Test class ObjectServiceTest contains the following code:
public class ObjectServiceTest
{
var objectToValidate = new Object(validPropertyA, validPropertyB);
using(var mock = new AutoMock.GetStrict())
{
var mockObjectService = new Mock<IObjectService>();
mockObjectService.callBase = true;
mockObjectService.Setup(s => s.ValidateObjectPropertyB(objectToValidate.PropertyB, _user.Id)).Returns(true);
var service = mock.Create<ObjectService>();
var result = service.ValidateObject(objectTovalidate);
Assert.IsTrue(result);
}
}
The above test fails because result is false, the for PropertyA succeeds
What am I doing wrong?

ValidateObject works in part by calling ValidateObjectPropertyB. I am presuming you are wanting to mock this second method so that you can demonstrate that ValidateObject does indeed call ValidateObjectPropertyB (provided !String.IsNullOrEmpty(objectToValidate.PropertyA) evaluates to true)
If this is the case then you are testing implementation detail, which generally you shouldn't do. Consider a function that took two integer values and returned their sum, you would want to verify that when this function was passed 3 and 5 it returned 8, you should not test that it arrived at this answer by using a particular method/class under the hood because this is not relevant to the desired outcome and should in future you decide you wished to refactor your code the test would likely start failing even if the code still returned the desired result.
Looking at your code, it seems that return value of ValidateObject is not directly dependent on the method call to ValidateObjectPropertyB but rather the value of validationResult. It is this value that you must set to properly test ValidateObject.
One way to achieve what you are asking would be to make ValidateObjectPropertyB virtual, then create a derived class that overrides this method to return what ever you want. However I do not recommend doing this purely for the sake of unit testing.

Related

Moq Unit Testing - expected result?

I'm using Moq for my Unit Tests and have got the following method:
[TestMethod]
public void GetTestRunById_ValidId_TestRunReturned()
{
var mockTestRunRepo = new Mock<IRepository<TestRun>>();
var testDb = new Mock<IUnitOfWork>();
testDb.SetupGet(m => m.TestRunsRepo).Returns(mockTestRunRepo.Object);
TestRun returnedRun = EntityHelper.getTestRunByID(testDb.Object, 1);
}
The method in question which is being tested is getTestRunByID(). I have confirmed that this method is called when debugging this unit test, but as expected getTestRunByID() doesn't return anything since the mock has no data inside it.
Would all that matter is the method gets hit and returns null? If not, how can I add data to my mockTestRunRepo when it's only present as a returned value from testDb?
For reference the method being tested is:
public static TestRun getTestRunByID(IUnitOfWork database, int testRun)
{
TestRun _testRun = database.TestRunsRepo.getByID(testRun);
return _testRun;
}
The purpose of the unit test is to ONLY test the small method getTestRunByID. For that, test if it was called exactly once with that integer parameters, 1.
mockTestRunRepo.Verify(m => m.getByID(1), Times.Once());
You must also set up the method getByID for mockTestRunRepo, to make it return a specific value, and test if the result value of the test run is equal to what you expected.
//instantiate something to be a TestRun object.
//Not sure if abstract base class or you can just use new TestRun()
mockTestRunRepo.Setup(m => m.getByID(1)).Returns(something);
Test if you get the same value
TestRun returnedRun = EntityHelper.getTestRunByID(testDb.Object, 1);
Assert.AreEqual(returnedRun, something);
This code might be prone to errors, as I do not have an environment to test it right now. But this is the general idea behind a unit test.
This way, you test if the method getById runs as expected, and returns the expected result.
You have your repository return data the same way that you setup everything else.
var mockTestRunRepo = new Mock<IRepository<TestRun>>();
// This step can be moved into the individual tests if you initialize
// mockTestRunRepo as a Class-level variable before each test to save code.
mockTestRunRepo.Setup(m => m.getById(1)).Returns(new TestRun());
Per #Sign's recommendation, if you know that you're calling it with 1, then use that instead of It.IsAny<int>() to keep things cleaner.

Moq Test error Null on Service Layer

How can the following test be corrected to work?
[TestMethod()]
public void GetEmployeeProductivityTest()
{
var mockHR = new Mock<IRepository<Employee>>();
var mockCMS = new Mock<ICMS_Repository>();
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<string>())).Verifiable();
Employee newEmp = new Employee();
newEmp.User_Name = "testName";
var service = new EmployeeService(mockHR.Object,mockCMS.Object);
var createResult = service.GetEmployeeByUserName(newEmp);
Assert.AreEqual(newEmp, createResult);
mockCMS.VerifyAll();
}
I get the following:
Assert.AreEqual failed. Expected:<Employee>. Actual:<(null)>.
As Requested this is the GetEmployeeByUserName() function being called:
public Employee GetEmployeeByUserName(Employee employee)
{
return _employeeRespository.Find().ByUserName(employee); <------(Using Strict: Gives me the following: All invocations on the mock must have a corresponding setup.)
}
Since you edited your question to show the behaviour of the GetEmployeeByUserName, it's now easy to explain why your test was failing.
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<string>()))
Here you set up an expectation that the FindEmployeeByUsername(string) overload would be called, but then you go on to use the FindEmployeeByUsername(Employee) overload. Moq setups are for specific overloads so when the method is called the mocked service finds no matching setup. If there is no matching setup, the mock either returns the default value for the Employee type (null), or throws an exception, depending on which MockBehavior you chose.
In your updated test, you fixed this by setting up the overload that you actually use.
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<Employee>()))
With simple methods like your GetEmployeeByUserName, mocking the dependencies and unit testing it can seem like a lot of overhead. What your test says is basically,
"when someone calls the GetEmployeeByUserName method on the EmployeeService,
the service should call the correct method on its repository"
Is this an important thing to assert? That's up to you to decide. As the complexity of your service methods increases, however, being able to isolate the dependencies and test their interactions will become more and more valuable.
You need to seed the FindEmployeeByUsername() Method of your mock:
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<string>())).Returns(newEmp);
otherwise it wont return the expected object, while called within the EmployeeService.
Instead of using multiple repositories which I think was confusing. I simplified it and it works now! Except I'm still not sure how this helps me code better. What did I accomplish with this? (I'm new to Testing/Moq/Integration Tests...etc..) I would really like an answer...to this..
public void GetEmployeeUsername_Using_EmployeeClass()
{
var mockCMS = new Mock<ICMS_Repository>(MockBehavior.Strict);
Employee newEmp = new Employee();
newEmp.User_Name = "testName";
mockCMS.Setup(repos => repos.FindEmployeeByUsername(It.IsAny<Employee>())).Returns(newEmp);
var service = new EmployeeService(mockCMS.Object);
var createResult = service.GetEmployeeByUserName(newEmp);
Assert.AreEqual(newEmp, createResult);
}

Optional parameters with a stub in RhinoMock

I want to stub a function that receive 2 boolean parameters. The first is required and the second is optional. If I try to send Arg.Is.Anything to the first but without information for the second, I receive an error:
System.InvalidOperationException : When using Arg, all arguments must be defined using Arg.Is, Arg.Text, Arg.List, Arg.Ref or Arg.Out. 2 arguments expected, 1 have been defined.
Here is a sample of my class to stub:
public interface IOptionalParameterTester
{
bool IsValid(bool mustCheck, bool checkInDatabase = true);
}
public class OptionalParameterTester : IOptionalParameterTester
{
public bool IsValid(bool mustCheck, bool checkInDatabase = true)
{
if (checkInDatabase)
return true;
else
return false;
}
}
And here is a sample of the test:
[Test]
public void ValidateProducerTest()
{
IOptionalParameterTester optionalParameter = MockRepository.GenerateStub<IOptionalParameterTester>();
optionalParameter.Stub(x => x.IsValid(Arg<bool>.Is.Anything)).Return(true);
}
In this case, if I want the test to pass without error, I must define the same information that for the first (Arg.Is.Anything) or a specific boolean value like true or false.
If I set anything other than Arg.Is.Anything for the first parameter, I don't have any error.
Is it a bug?
Can I setup an option in RhinoMock to don't have to define a value for each optional parameter?
If there is no setup, is there a better thing to do to handle this case (Best practice, pattern, etc.)?
Thank you.
I think I understand what you are trying to do but, since it seems that this is a limitation of Rhino Mocks (we can get to that conclusion from the error message you are receiving) I would suggest to change your testing strategy.
Try doing the following:
[Test]
public void ValidateProducerTest()
{
bool anyBooleanValue = true;
IOptionalParameterTester optionalParameter = MockRepository.GenerateStub<IOptionalParameterTester>();
optionalParameter.Stub(x => x.IsValid(anyBooleanValue)).Return(true);
}
I know that on your test you want Rhino Mocks to ignore the first parameter and that it takes the optional second one but, depending on the logic you want to test, just hard code the first parameter and Rhino Mocks should not complain.
As long as on your test it is clearly stated that the first parameter's value is not relevant your test is valid and readable.
Just had a similar issue myself, try
optionalParameter.Stub(x => x.IsValid()).IgnoreArguments().Return(true);
This is quite an old question now, but I landed on this page because I was having issues with AssertWasCalled and optional parameters.
Eventually, I solved my problem using the following syntax found on this page: http://petermorlion.blogspot.com/2012/11/rhinomock-assertwascalled-vs.html.
string expectedMessage = "RhinoMocks baby!";
string actualMessage = "RhinoMocks dude!";
var fooMock = MockRepository.GenerateMock<ifoo>();
fooMock.Bar(actualMessage);
var calls = fooMock.GetArgumentsForCallsMadeOn(x => x.Bar(string.Empty), o => o.IgnoreArguments());
Assert.AreEqual(1, calls.Count);
var arguments = calls[0];
Assert.AreEqual(expectedMessage, arguments[0]);

Proper way to verify parameters being passed to a Mock are set as expected

Is it acceptable to do asserts in your callbacks if you later verify that the methods were called? Is this the preferred way of making sure my mock is getting the expected parameters passed to it, or should I set a local variable in my callback and do the asserts on that instance?
I have a situation where I have some logic in a Presenter class that derives values based on inputs and passes them to a Creator class. To test the logic in the Presenter class I want to verify that the proper derived values are observed when the Creator is called. I came up with the example below that works, but I'm not sure if I like this approach:
[TestFixture]
public class WidgetCreatorPresenterTester
{
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) =>
Assert.AreEqual("Derived.Name", widget.DerivedName));
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
}
}
I'm concerned because without the Verify call at the end, there is no guarantee that the assert in the callback would be invoked. Another approach would be to set a local variable in the callback:
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
I feel that this approach is less error prone since it is more explicit, and it's easier to see that the Assert statements will be called. Is one approach preferable to the other? Is there a simpler way to test the input parameter passed to a mock that I'm missing?
In case it is helpful, here is the rest of the code for this example:
public class Widget
{
public string Name { get; set; }
public string DerivedName { get; set; }
}
public class WidgetCreatorPresenter
{
private readonly IWidgetCreator _creator;
public WidgetCreatorPresenter(IWidgetCreator creator)
{
_creator = creator;
}
public void Save(string name)
{
_creator.Create(
new Widget { Name = name, DerivedName = GetDerivedName(name) });
}
//This is the method I want to test
private static string GetDerivedName(string name)
{
return string.Format("Derived.{0}", name);
}
}
public interface IWidgetCreator
{
void Create(Widget widget);
}
EDIT
I updated the code to make the second approach I outlined in the question easier to use. I pulled creation of the expression used in Setup/Verify into a separate variable so I only have to define it once. I feel like this method is what I'm most comfortable with, it's easy to setup and fails with good error messages.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
Expression<Action<IWidgetCreator>> expressionCreate =
(w => w.Create(It.IsAny<Widget>()));
widgetCreator.Setup(expressionCreate)
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(expressionCreate, Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
What I do is do the Verify with matches in keeping with AAA. And becuase of this the Setup is not required. You can inline it but I separated it out to make it look cleaner.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(MatchesWidget("Derived.Name"));
}
private Widget MatchesWidget(string derivedName)
{
return It.Is<Widget>(m => m.DerivedName == derivedName);
}
Because of the way your code is structured, you're kind of forced to test two things in one unit test. You're testing that A) your presenter is calling the injected WidgetCreator's create method and B) that the correct name is set on the new Widget. If possible, it'd be better if you can somehow make these two things two separate tests, but in this case I don't really see a way to do that.
Given all that, I think the second approach is cleaner. It's more explicit as to what you're expecting, and if it fails, it'd make perfect sense why and where it's failing.
Just to elaborate on #rsbarro's comment - the Moq failure error message:
Expected invocation on the mock at least once, but was never performed
... is less than helpful for complex types, when determining exactly which condition actually failed, when hunting down a bug (whether in the code or unit test).
I often encounter this when using Moq Verify to verify a large number of conditions in the Verify, where the method must have been called with specific parameter values which are not primitives like int or string.
(This is not typically a problem for primitive types, since Moq lists the actual "performed invocations" on the method as part of the exception).
As a result, in this instance, I would need to capture the parameters passed in (which to me seems to duplicate the work of Moq), or just move the Assertion inline with Setup / Callbacks.
e.g. the Verification:
widgetCreator.Verify(wc => wc.Create(
It.Is<Widget>(w => w.DerivedName == "Derived.Name"
&& w.SomeOtherCondition == true),
It.Is<AnotherParam>(ap => ap.AnotherCondition == true),
Times.Exactly(1));
Would be recoded as
widgetCreator.Setup(wc => wc.Create(It.IsAny<Widget>(),
It.IsAny<AnotherParam>())
.Callback<Widget, AnotherParam>(
(w, ap) =>
{
Assert.AreEqual("Derived.Name", w.DerivedName);
Assert.IsTrue(w.SomeOtherCondition);
Assert.IsTrue(ap.AnotherCondition, "Oops");
});
// *** Act => invoking the method on the CUT goes here
// Assert + Verify - cater for rsbarro's concern that the Callback might not have happened at all
widgetCreator.Verify(wc => wc.Create(It.IsAny<Widget>(), It.Is<AnotherParam>()),
Times.Exactly(1));
At first glance, this violates AAA, since we are putting the Assert inline with the Arrange (although the callback is only invoked during the Act), but at least we can get to the bottom of the issue.
Also see Hady's idea of moving the 'tracking' callback lambda into its own named function, or better still, in C#7, this can be moved to a Local Function at the bottom of the unit test method, so the AAA layout can be retained.
Building on top of StuartLC's answer in this thread, you follow what he is suggesting without violating AAA by writing an "inline" function that is passed to the Verify method of a mock object.
So for example:
// Arrange
widgetCreator
.Setup(wc => wc.Create(It.IsAny<Widget>(), It.IsAny<AnotherParam>());
// Act
// Invoke action under test here...
// Assert
Func<Widget, bool> AssertWidget = request =>
{
Assert.AreEqual("Derived.Name", w.DerivedName);
Assert.IsTrue(w.SomeOtherCondition);
Assert.IsTrue(ap.AnotherCondition, "Oops");
return true;
};
widgetCreator
.Verify(wc => wc.Create(It.Is<Widget>(w => AssertWidget(w)), It.Is<AnotherParam>()), Times.Exactly(1));

Rhino Mocks Restub function

Sometimes I stub dependencies in test class setup and then want to restub some of them in concrete test. But Rhino mocks remembers only the first stub value and it is a bit inconvenient.
someStub.Stub(x => x.SomeMethod(1)).Return(100);
var value1 = someStub.SomeMethod(1);
someStub.Stub(x => x.SomeMethod(1)).Return(200);
var value2 = someStub.SomeMethod(1);
value 2 will be equal to 100.
Is it a designed behaviour? Are there any workarounds?
I ran into a need to do this myself. I worked around it by using the WhenCalled function where you pass in an action to be executed when the function is called. This will give you more flexibility on what you can return at different points.
More info/activity on this stackoverflow thread:
Rhino Mocks: Re-assign a new result for a method on a stub and here:
Changing previously stubbed calls with Rhino Mocks.
I know this is old but hope it helps someone else.
You can work around it with inheritance. If you have a base test class and some test subclasses that run the tests, you can make the return value a protected property of the base test class, and set the value in the subclasses at a point before base. Initialize is called.
So (using MSTEST) you could have:
in your base class:
protected int ReturnVal{get; set;}
public void Init()
{
someStub = MockRepository.GenerateMock<ISomeStub>();
someStub.Stub(x => x.SomeMethod(1)).Return(ReturnVal);
}
in your subclass:
[TestInitialize]
public override Init()
{
ReturnVal = 200;
base.Init();
}
Yes, this is the designed behaviour.
The workaround I use most of the time is to create a helper method that will set up the stub for you, i.e.:
private X MockX()
{
return MockX(100);
}
private X MockX(int returnValue)
{
var x = MockRepository.GenerateStub<X>();
someStub.Stub(x => x.SomeMethod(1)).Return(returnValue);
return x;
}
and then in your test instead of using a mock created in SetUp, you call the appropriate function. The added benefit is that it is clear that your test is using some special values of the return values.
You can use mocks instead of stubs to record a scenario like that:
[Test]
public void Mytest()
{
var mocks = new MockRepository();
var someMock = mocks.DynamicMock<IFoo>();
someMock.SomeMethod(1);
LastCall.Return(100);
someMock.SomeMethod(1);
LastCall.Return(200);
mock.Replay(); // stop recording, go to replay mode
// actual test, normally you would test something which uses the mock here
int firstResult = someMock.SomeMethod(1);
int secondResult = someMock.SomeMethod(2);
// verify the expectations that were set up earlier
// (will fail if SomeMethod is not called as in the recorded scenario)
someMock.VerifyAll();
}
Mocks in Rhino Mocks are more complicated to set up than stubs. They also mix the definition of behavior with the creation of assertions (the record phase does both), and they rely on the ordering of method calls. This makes for brittle tests; stick to stubs unless you really need mocks.

Categories