I wrote the following test case to illustrate my problem using Rhino Mocks:
[TestClass]
public class Tester
{
public class TestList<T> : List<T>
{
public override bool Equals(object obj)
{
// obj is an empty list here??
return base.Equals(obj);
}
}
public interface IStubbedInterface
{
void DoSomethingWithList(TestList<int> list);
}
public class ClassToTest
{
public IStubbedInterface TheStub { get; set; }
public void Run()
{
var list = new TestList<int> { 1, 2 };
TheStub.DoSomethingWithList(list);
list.Clear();
}
}
public bool Match(TestList<int> arg)
{
// Here arg is an empty list??
return arg == new TestList<int> { 1, 2 };
}
[TestMethod]
public void Test()
{
var classToTest = new ClassToTest();
classToTest.TheStub = MockRepository.GenerateMock<IStubbedInterface>();
classToTest.Run();
classToTest.TheStub.AssertWasCalled(
x => x.DoSomethingWithList(new TestList<int>() { 1, 2 }));
//x => x.DoSomethingWithList(Arg<TestList<int>>.Matches(arg => Match(arg))));
}
}
The test case will fail on the AssertWasCalled() line, no matter if I compare the list directly or using the Arg<>.Matches(..) syntax. I also tried with MockRepository.GenerateStub<>(..) instead of GenerateMock<>(..), which also fails. It fails because of the list.Clear(); line after calling DoSomethingWithList(), which results in the list also being empty at the time of AssertWasCalled(). Is this a bug with RhinoMocks? I would have assumed that RhinoMocks would record a snapshot of the argument somehow when the asserted function was called, but it looks like RhinoMocks keeps using the same object?
In the real case where I encountered this problem the argument of the function I was testing was wrapped in a using() statement, which lead to the same effect of AssertWasCalled not being able to test the arguments passed.
Looks like using the Expect()/VerifyAllExpectations() pattern works better for this test scenario. Changing the test case to the below code will pass.
This is rather unfortunate as I much prefer using AssertWasCalled(), however as it stands it is rather unreliable.
[TestMethod]
public void Test()
{
var classToTest = new ClassToTest();
classToTest.TheStub = MockRepository.GenerateMock<IStubbedInterface>();
classToTest.TheStub.Expect(
x => x.DoSomethingWithList(new TestList<int>() { 1, 2 }));
classToTest.Run();
classToTest.TheStub.VerifyAllExpectations();
}
Related
How to get the parameters count which is passing to the function using Nunit mocking for assertion and that function called inside another function.
For e.g:
public class TestClass
{
public string Name {get;set;}
public int Id {get;set;}
}
public void ProcessData(IEnumerable<EventData> events)
{
List<TestClass> testClasses = new();
events.ForEach(msg => {
var testClass = JsonConvert.DeserializeObject<TestClass>(msg.EventBody.ToString());
if(testClass != null)
{
testClasses.Add(testClass);
}
});
if(testClasses.Count > 0)
{
BulkUpdateData(testClasses);
}
}
public void BulkUpdateData(List<TestClass> testClasses)
{ ... }
Now, I need to do unit testing this "ProcessData" method.
For this using NUnit framework in .Net 6.0.
I can pass test data to "ProcessData" method by mocking while writing unit test cases.
But here my case is,
Consider now I'm passing 10 values in a list to "ProcessData". In that only 8 got passed to "BulkUpdateData" method since 2 values are not got deserialized due to invalid data.
Here how to get this BulkUpdateData got 8 values inside the "ProcessData" method.
I need to get this count value for assertion.
Kindly suggest on this.
Your ProcessData() method needs to return something. Either an int representing the count of processed testclasses, or List<TestClass>.
With your ProcessData() method now returning something, you can then go ahead and write your asserts, knowing exactly how many testclasses were passed to BulkUpdateData() method.
public IEnumerable<TestClass> ProcessData(IEnumerable<EventData> events)
{
List<TestClass> testClasses = new();
events.ForEach(msg => {
var testClass = JsonConvert.DeserializeObject<TestClass>(msg.EventBody.ToString());
if (testClass != null)
{
testClasses.Add(testClass);
}
});
if (testClasses.Count > 0)
{
BulkUpdateData(resultOfProcessData);
}
return testClasses;
}
If I misunderstood your question and actually, you want to unit test BulkUpdateData() method, in your [TestFixture] you could add an instance variable to hold either the count or the list of TestClass objects. And you could take advantage of the [OrderAttribute] and organize your tests like this:
[TestFixture]
public class UnitTests
{
List<TestClass> resultOfProcessData = new();
[Test]
[Order(1)]
public void ProcessDataUnitTest()
{
resultOfProcessData = ProcessData(events);
}
[Test]
[Order(2)]
public void BulkUpdateDataUnitTest()
{
if (resultOfProcessData.Count > 0)
{
BulkUpdateData(resultOfProcessData);
}
}
public IEnumerable<TestClass> ProcessData(IEnumerable<EventData> events)
{
List<TestClass> testClasses = new();
events.ForEach(msg => {
var testClass = JsonConvert.DeserializeObject<TestClass>(msg.EventBody.ToString());
if (testClass != null)
{
testClasses.Add(testClass);
}
});
return testClasses;
}
public void BulkUpdateData(List<TestClass> testClasses)
{ ... }
}
Hope this helps.
I ran into a failing unit test in a complex piece of code and the Moq logging wasn't doing it for me. I need to know what's different between what I expected a method to be called with and what it was actually called with. I ended up attaching a debugger to the unit test and that way I could look into the object being passed to the moq and manually compare all its values. All this effort would not be neccesary if I got more information from the Verify error message.
How do I log the differences between these two things?
What I expected the mocked method to be called with
What the mocked method was actually called with
A simplified example:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace MyNamespace
{
[TestClass]
public class MyTestClass
{
[TestMethod]
public void MyTestMethod()
{
// Arrange
var serviceMock = new Mock<IService>();
var model = new Model
{
Word = "Foo",
Number = 1
};
var servicecaller = new ServiceCaller(serviceMock.Object);
// Act
servicecaller.CallService(model);
// Assert
serviceMock.Verify(mock =>
mock.Call(
It.Is<Model>(m =>
m.Word == "Bar"
&& m.Number == 1)));
}
}
public class ServiceCaller
{
private IService _service;
public ServiceCaller(IService service)
{
_service = service;
}
public void CallService(Model model)
{
_service.Call(model);
}
}
public interface IService
{
void Call(Model model);
}
public class Model
{
public int Number { get; set; }
public string Word { get; set; }
}
}
When you run this test, it fails and shows this message:
Test method MyNamespace.MyTestClass.MyTestMethod threw exception:
Moq.MockException:
Expected invocation on the mock at least once, but was never performed: mock => mock.Call(It.Is<Model>(m => m.Word == "Bar" && m.Number == 1))
No setups configured.
Performed invocations:
IService.Call(Model)
But I want it to log something along the lines of:
Performed invocations:
IService.Call(Model { Word: "Bar", Number: 1 })
Or even better:
"Assert failed for the object passed to IService.Call: The Model.Word 'Foo' is not equal to 'Bar'".
You'll probably have to verify the invocations via Mock.Invocations which is a sequence of all invocations on the mock along with the arguments that were provided. Something like the following:
var callInvocations = serviceMock.Invocations.Where(x => x.Method.Name.Equals(nameof(IService.Call)));
var matchingInvocations = callInvocations.Where(x =>
{
var model = x.Arguments.First() as Model;
return model.Word.Equals("Bar") && model.Number == 1;
});
if (!matchingInvocations.Any())
{
throw new Exception($"Performed invocations:{Environment.NewLine}{string.Join(Environment.NewLine, callInvocations.Select(x => $"{x.Method.DeclaringType.Name}.{x.Method.Name}({string.Join(", ", x.Method.GetParameters().Select((y, i) => $"{y.ParameterType.Name} {JsonConvert.SerializeObject(x.Arguments[i])}"))})"))}");
}
will give the desired output:
I'm trying to test some code I've written have run in to issues trying to mock a func using Machine.Fakes (which uses Moq under the hood). See the code below for an example.
public class RoutingEngine : IRoutingEngine
{
private readonly IMessageRouters _messageRouters;
public RoutingEngine(IMessageRouters messageRouters)
{
_messageRouters = messageRouters;
}
public void Route<T>(T inbound)
{
var messageRouters = _messageRouters.Where(x => x.CanRoute(inbound));
foreach(var router in messageRouters)
router.Route(inbound);
}
}
public class MessageRouters : IMessageRouters
{
public IList<IMessageRouter> _routers = new List<IMessageRouter>();
public IEnumerable<IMessageRouter> Where(Func<IMessageRouter, bool> func)
{
return _routers.Where(func);
}
public void Add(IMessageRouter messageRouter)
{
_routers.Add(messageRouter);
}
}
And the test is here
public class when_routing_a_message_with_fakes : WithSubject<RoutingEngine>
{
Establish that = () =>
{
Message = new MyMessage{ SomeValue= 1, SomeOtherValue = 11010 };
Router = The<IMessageRouter>();
Router.WhenToldTo(x => x.CanRoute(Message)).Return(true);
The<IMessageRouters>().WhenToldTo(x => x.Where(router => router.CanRoute(Message))).Return(new List<IMessageRouter> { Router });
};
Because of = () => Subject.Route(Message);
It should_do_route_the_message = () => Subject.WasToldTo(x => x.Route(Param.IsAny<MyMessage>()));
static MyMessage Message;
static IMessageRouter Router;
}
I get an unsupported expression for the above so I changed the where method on the IMessageRouters to the following:
public IEnumerable<IMessageRouter> Where(Expression<Func<IMessageRouter, bool>> func)
{
return _routers.Where(func.Compile());
}
Now I get this error
Object instance was not created by Moq.
Parameter name: mocked
Any ideas?
EDIT
So I tried writing another test without machine.fakes, as per Mocking methods with Expression<Func<T,bool>> parameter using Moq. Turns out it's an obvious problem. The func used in the real RoutingEngine is not being mocked
The<IMessageRouters>()
.WhenToldTo(x => x.Where(router => router.CanRoute(Param.IsAny<ProcessSkuCostUpdated>())))
.Return(new List<IMessageRouter> {Router});
The above has no bearing on the Where being executed at runtime and can't be as the func is compiled down to a private method at compile time. Seems like to mock the func, I need to push it up to an interface. Smells though as I'm pushing up internal behavior purely for testing.
I see two issues with your test code:
The expression you use for setting up the Where() call on IMessageRouters is too explicit. It should not care about what exact function is passed.
You are verifying whether Route() has been called on the Subject. Instead you should verify whether the Message has been passed to the IMessageRouter.
As an additional improvement, you can omit the Router field and use The<IMessageRouter>() directly.
[Subject(typeof(RoutingEngine))]
public class when_routing_a_message_with_fakes : WithSubject<RoutingEngine>
{
Establish that = () =>
{
Message = new MyMessage { SomeValue = 1, SomeOtherValue = 11010 };
The<IMessageRouter>().WhenToldTo(x => x.CanRoute(Message)).Return(true);
The<IMessageRouters>().WhenToldTo(x => x.Where(Param<Func<IMessageRouter, bool>>.IsAnything))
.Return(new List<IMessageRouter> { The<IMessageRouter>() });
};
Because of = () => Subject.Route(Message);
It should_route_the_message = () =>
The<IMessageRouter>().WasToldTo(x => x.Route(Message));
static MyMessage Message;
}
I see a way to avoid mocking the Func<> at all. I hope it's interesting to you :) Why not forget about the generalized Where(Func<>) method and provide the specific query method. You own the inbound messages and the router(s).
public class MessageRouters : IMessageRouters
{
public IList<IMessageRouter> _routers = new List<IMessageRouter>();
public IEnumerable<IMessageRouter> For<T>(T inbound)
{
return _routers.Where(x => x.CanRoute(inbound));
}
public void Add(IMessageRouter messageRouter)
{
_routers.Add(messageRouter);
}
}
The class under test becomes simpler (in signature, no Func<>).
public class RoutingEngine : IRoutingEngine
{
private readonly IMessageRouters _messageRouters;
public RoutingEngine(IMessageRouters messageRouters)
{
_messageRouters = messageRouters;
}
public void Route<T>(T inbound)
{
var messageRouters = _messageRouters.For(inbound);
foreach(var router in messageRouters)
router.Route(inbound);
}
}
I'm guessing you don't need to inspect the actual instance of the inbound message either, maybe you can get away with just a Type check, like
public IEnumerable<IMessageRouter> For<T>() { ... }
and
var messageRouters = _messageRouters.For<T>();
You don't have to mock any Func<>s now and you can just do an assert-was-called (or however that looks in Moq).
I am using Moq library for unit testing. Now what i want is that when I access my object for the first time it should return null, and when i access this on second time it should return something else.
here is my code
var mock = new Mock<IMyClass>();
mock.Setup(?????);
mock.Setup(?????);
var actual = target.Method(mock.object);
in my method i am first checking that whether mock object is null or not, if it is null then do initialize it and then do some calls on it.
bool Method(IMyClass myObj)
{
if (myObj != null)
return true;
else
{
myObj = new MyClass();
bool result = myObj.SomeFunctionReturningBool();
return result;
}
}
what to do setup for mock object,
Also i need to know how to mock this line
bool result = myObj.SomeFunctionReturningBool();
It sounds like you are trying to run two tests with one test method - maybe it would be better to split the tests into two?
You also want to initialise a new object if the method is passed null. To test this, I suggest creating a factory object responsible for creating instances of MyClass. The new code would look like:
interface IMyClassFactory
{
IMyClass CreateMyClass();
}
bool Method(IMyClass myObj, IMyClassFactory myClassFactory)
{
if (myObj != null)
{
return true;
}
myObj = myClassFactory.CreateMyClass();
return myObj.SomeFunctionReturningBool();
}
Then the tests would look like:
[Test]
public void Method_ShouldReturnTrueIfNotPassedNull()
{
Assert.That(target.Method(new MyClass()), Is.True);
}
[Test]
public void Method_ShouldCreateObjectAndReturnResultOfSomeFunctionIfPassedNull()
{
// Arrange
bool expectedResult = false;
var mockMyClass = new Mock<IMyClass>();
mockMyClass.Setup(x => x.SomeFunctionReturningBool()).Returns(expectedResult);
var mockMyFactory = new Mock<IMyClassFactory>();
mockMyFactory.Setup(x => x.CreateMyClass()).Returns(mockMyClass.Object);
// Act
var result = target.Method(null, mockMyFactory.Object);
// Assert
mockMyClass.Verify(x => x.SomeFunctionReturningBool(), Times.Once());
mockMyFactory.Verify(x => x.CreateMyClass(), Times.Once());
Assert.That(result, Is.EqualTo(expectedResult));
}
Here the factory pattern has been used to pass in an object which can create objects of IMyClass type, and then the factory itself has been mocked.
If you do not want to change your method's signature, then create the factory in the class's constructor, and make it accessible via a public property of the class. It can then be overwritten in the test by the mock factory. This is called dependency injection.
Moq - Return null - This working example simply illustrates how to return null using Moq. While the line of code is required is the commented line below, a full working example is provided below.
// _mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
}
public interface IShopService
{
Product GetProduct(string productId);
}
public class ShopService : IShopService
{
public Product GetProduct(string productId)
{
if (string.IsNullOrWhiteSpace(productId))
{
return new Product();
}
return new Product { Id = "8160807887984", Name = "How to return null in Moq" };
}
}
public class Shop
{
private static IShopService _shopService;
public Shop(IShopService shopService)
{
_shopService = shopService;
}
public Product GetProduct(string productId)
{
Product product = _shopService.GetProduct(productId);
return product;
}
}
[TestClass]
public class ShopTests
{
Mock<IShopService> _mockShopService;
[TestInitialize]
public void Setup()
{
_mockShopService = new Mock<IShopService>();
}
[TestMethod]
public void ShopService_GetProduct_Returns_null()
{
//Arrange
Shop shop = new Shop(_mockShopService.Object);
//This is how we return null --- all other code above is to bring this line of code home
_mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);
//Act
var actual = shop.GetProduct(It.IsAny<string>());
//Assert
Assert.IsNull(actual);
}
}
To mock a result value you can do simply:
mock.Setup(foo => foo.SomeFunctionReturningBool()).Returns(true); // or false :)
for the other question, just pass null in the unit test instead of passing mock.object and your unit test cover that too. So you basically create two unit test one with:
var actual = target.Method(mock.object);
and the other one with:
var actual = target.Method(null);
Currently your SUT is tight-coupled with MyClass implementation. You can't mock objects which are instantiated with new keyword inside your SUT. Thus you cannot test your SUT in isolation, and your test is not unit test anymore. When implementation of MyClass.SomeFunctionReturningBool will change (it will return true instead of false), tests of your SUT will fail. This shouldn't happen. Thus, delegate creation to some dependency (factory) and inject that dependency to your SUT:
[Test]
public void ShouldReturnTrueWhenMyClassIsNotNull()
{
Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
Mock<IMyClass> myClass = new Mock<IMyClass>();
var foo = new Foo(factory.Object);
Assert.True(foo.Method(myClass.Object));
}
[Test]
public void ShouldCreateNewMyClassAndReturnSomeFunctionValue()
{
bool expected = true;
Mock<IMyClass> myClass = new Mock<IMyClass>();
myClass.Setup(mc => mc.SomeFunctionReturningBool()).Returns(expected);
Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
factory.Setup(f => f.CreateMyClass()).Returns(myClass.Object);
var foo = new Foo(factory.Object);
Assert.That(foo.Method(null), Is.EqualTo(expected));
factory.VerifyAll();
myClass.VerifyAll();
}
BTW assignment new value to method parameter does not affect reference which you passed to method.
Implementation:
public class Foo
{
private IMyClassFactory _factory;
public Foo(IMyClassFactory factory)
{
_factory = factory;
}
public bool Method(IMyClass myObj)
{
if (myObj != null)
return true;
return _factory.CreateMyClass().SomeFunctionReturningBool();
}
}
You can use TestFixture with parameter. this test will run two times and different type value.
using NUnit.Framework;
namespace Project.Tests
{
[TestFixture(1)]
[TestFixture(2)]
public class MyTest
{
private int _intType;
public MyTest(int type)
{
_intType = type;
}
[SetUp]
public void Setup()
{
if (_intType==1)
{
//Mock Return false
}
else
{
//Mock Return Value
}
}
}
}
I have a clas that is something like this
public class MyClass
{
public virtual string MethodA(Command cmd)
{ //some code here}
public void MethodB(SomeType obj)
{
// do some work
MethodA(command);
}
}
I mocked MyClass as PartialMock (mocks.PartialMock<MyClass>) and I setup expectation for MethodA
var cmd = new Command();
//set the cmd to expected state
Expect.Call(MyClass.MethodA(cmd)).Repeat.Once();
Problem is that MethodB calls actual implementation of MethodA instead of mocking it up. I must be doing something wrong (not very experienced with RhinoMocks). How do I force it to mock MetdhodA?
Here is the actual code:
var cmd = new SetBaseProductCoInsuranceCommand();
cmd.BaseProduct = planBaseProduct;
var insuredType = mocks.DynamicMock<InsuredType>();
Expect.Call(insuredType.Code).Return(InsuredTypeCode.AllInsureds);
cmd.Values.Add(new SetBaseProductCoInsuranceCommand.CoInsuranceValues()
{
CoInsurancePercent = 0,
InsuredType = insuredType,
PolicySupplierType = ppProvider
});
Expect.Call(() => service.SetCoInsurancePercentages(cmd)).Repeat.Once();
mocks.ReplayAll();
//act
service.DefaultCoInsurancesFor(planBaseProduct);
//assert
service.AssertWasCalled(x => x.SetCoInsurancePercentages(cmd),x=>x.Repeat.Once());
I've tried to reproduce this issue, and it seems to work fine, what is different between my test code (below) and yours?
public class MyClass
{
public virtual string MethodA(object cmd)
{
return "implementation";
}
public string MethodB(object obj)
{
// do some work
return MethodA(obj);
}
}
[TestFixture]
public class MyClassTests
{
[Test]
public void MockTest()
{
var myClassMock = MockRepository.GenerateMock<MyClass>();
myClassMock.Expect(x => x.MethodA("x")).Return("mock");
Assert.AreEqual("mock", myClassMock.MethodB("x"));
myClassMock.VerifyAllExpectations();
}
}
The issue here seems to be that while in your comments you said PartialMock, but in your code sample you use DynamicMock. I believe this is the source of your issues, as they behave differently.