How to get passing parameter count in a function NUNIT mocking assertion? - c#

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.

Related

Rhino mocks AssertWasCalled does not work

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();
}

Mocking an object initialised inside a method under test

I am trying to test a class which instatiates another class within it. It is the instatinated class call I want to mock.
Is this possible or is they a way around it/ simpler way I am missing?
Below I have written up a simpler example which still has the same problemts as my main code.
public interface my_interface
{
int returns_25();
}
public class class_i_want_to_mock : my_interface
{
public int returns_25()
{
// TEST SHOULD FAIL SO NEED MOCK TO PASS THE CASE
return 7645745;
}
}
In another namespace (it has access):
public class class_to_test
{
public static int returns_25()
{
class_i_want_to_mock _tempClass= new class_i_want_to_mock ();
// Will return 7645745 unless moq changes return value
int _temp_int = _tempClass.returns_25()
return _temp_int;
}
}
My test (which fails):
[Test]
public void test_returns_25()
{
// Mock
Mock<my_interface> myMock = new Mock<my_interface>();
myMock.Setup(m => m.returns_25()).Returns(25);
// Act
int return_number = class_to_test.returns_25();
// Assert
Assert.AreEqual(25, return_number);
}
Here is working code thanks to the injection idea from JSteward above.
Code is in same order
public interface my_interface
{
int returns_25();
}
public class class_i_want_to_mock : my_interface
{
public int returns_25()
{
// TEST SHOULD FAIL SO NEED MOCK TO PASS THE CASE
return 7645745;
}
}
Next class, notice the injection of the interface
public class class_to_test
{
public static int returns_25(my_interface _temp_interface)
{
// Will return 7645745 unless moq changes return value
int _temp_int = _temp_interface.returns_25()
return _temp_int;
}
}
And the test. Note the object of the Mock class has to be used (myMock.Object)
[Test]
public void test_returns_25()
{
// Mock
Mock<my_interface> myMock = new Mock<my_interface>();
myMock.Setup(m => m.returns_25()).Returns(25);
// Act
int return_number = class_to_test.returns_25(myMock.Object);
// Assert
Assert.AreEqual(25, return_number);
}

MOQ: Setting up a method which fills a collection inside the object passed as parameter

I have a class named "CollectionPager" which has a collection inside that of type List. I have a method "RetrieveList" which takes a "CollectionPager" as input and populates "List" in side that. This method doesn't return any value.
I need to mock a function which calls "RetrieveList". However, since it doesn't return any value, whatever input was fed into Mock is not taken into consideration and this collection(List) always has a count of 0.
Any possible ways to resolve this?
I guess you need the Callback (see also Moq quickstart) method to setup some logic when mocking a void function.
Here is sample test which demonstrates the usage:
var mock = new Mock<IRetrieveListService>();
mock.Setup(m => m.RetrieveList(It.IsAny<CollectionPager>()))
.Callback<CollectionPager>(p =>
{
p.List.Add("testItem1");
p.List.Add("testItem2");
});
var sut = new OtherService(mock.Object);
sut.SomeMethodToTest();
Assuming your classes looks like something like these:
public class CollectionPager
{
public CollectionPager()
{
List = new List<string>();
}
public List<string> List { get; private set; }
}
public interface IRetrieveListService
{
void RetrieveList(CollectionPager pager);
}
public class RetrieveListService : IRetrieveListService
{
public void RetrieveList(CollectionPager pager)
{
pager.List.Add("item1");
pager.List.Add("item2");
}
}
public class OtherService
{
private readonly IRetrieveListService retrieveListService;
public OtherService(IRetrieveListService retrieveListService)
{
this.retrieveListService = retrieveListService;
}
public void SomeMethodToTest()
{
var collectionPager = new CollectionPager();
retrieveListService.RetrieveList(collectionPager);
// in your test collectionPager.Item contains: testItem1, testItem2
}
}

How to return null when accessing a moq object?

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
}
}
}
}

MOQ - How to verify static class call and delegates?

I just started reading on Moq framework and thought of applying it to my existing code. I could come up with a test case to verify basic function calls. But now stuck at applying it to delegates and static classes.
Below is the system under test (SUT)
public class SUT : ISUT
{
private IInterface1 i1;,
private IInterface2 i2;
public SUT(IInterface1 i1, IInterface2 i2)
{
this.i1 = i1;
this.i2 = i2;
}
public void FunctionToTest(Action<string> someDelegate, Action otherDelegate)
{
var list = i2.GetList();
foreach(var r in list)
{
i1.SomeFunction(r);
if(someDelegate != null)
someDelegate("message");
SomeHelper.LogData(r);
}
if(otherDelegate != null)
otherDelegate();
}
}
I have setup my test as below
[TestFixture]
public class when_list_contains_atleast_one_item
{
ISUT sut;
Mock<IInterface1> mockI1;
Mock<IInterface2> mockI2;
public SUT_Tester()
{
mockI1 = new Mock<IInterface1>();
mockI2 = new Mock<IInterface2>();
sut = new SUT(mockI1.Object, mockI2.Object);
}
[Test]
public void it_should_call_somefunction_calldelegates_and_log_data()
{
var dummyList = new List<string> { "string1", "string2" };
mockI2.Setup(m2 => m2.GetList()).Returns(dummyList).Verifiable();
sut.FunctionToTest(It.IsAny<Action<string>>(), It.IsAny<Action>());
// How to verify delegates were raised
// How to verify SomeHelper.LogData was called
mockI1.Verify(m => m.SomeFunction(It.IsAny<string>()), Times.Exactly(2));
mockI2.Verify();
}
}
How to verify that someDelegate and otherDelegate were raised ?
SomeHelper is a static class and LogData is a static function. How to verify that LogData was called?
Below is the SomeHelper class
public static class SomeHelper
{
static ILogger logger = LoggerManager.GetLogger("Something");
public static void LogData(string input)
{
logger.Info(input);
}
}
You cannot verify static methods since they cannot be mocked by Moq.
In order to verify calls on the delegates, create them so that they call a local function and you keep the state and verify:
string localString = string.Empty;
Action<string> action = (string s) => localString = s;
// ... pass it to the test
Assert.(localString == "TheStringItMustbe");
(UPDATE)
OK to check an action that has no in params, increment a local variable and assert if it has been incremented (or something similar):
int localVar = 0;
Action action = () => localVar++;
// ... pass it to the test
Assert.(localVar == 1);
You might want to consider changing the IInterface1/2 interfaces so that they either take an ILogger as a parameter into SomeFunction, or have a settable ILogger property.
Then you could pass a mocked ILogger into SomeFunction.

Categories

Resources