Home > Blockchain >  How do I mock a List of custom objects and set it up to return a real instance of an object
How do I mock a List of custom objects and set it up to return a real instance of an object

Time:08-11

I have a list of objects I need to mock:

var myMock = new Mock<IList<IValidatableTable>>();

My intention is to create a real instance of an object that implements IValidatableTable like so:

var validatableTable = new ValidatableTable();
//... code that modifies the object the way I need it...

And set my mock up so that it returns this object as one of the list items.

I have tried to use SetupGet, Setup, but I can't figure ou what to put into the lambda expression. I have also tried to google but there was only one thread that was close to what I am looking for c# How to mock a list of objects and even that didn't help, because my compiler can't resolve Catalogue.

Can you help me please?

CodePudding user response:

As long as you don't want to check whether the members of the list (e.g. Add, Remove) are called in a specific way, I'd not create a mock for the list, but create a real list. As List<T> is a basic and very commonly used member of the framework, it is perfectly fine to use in your test directly without mocking it.

IList<IValidatableTable> tables = new List<IValidatableTable>();

You can then fill this list either with mocks or real objects as needed for your test; if you want to check whether the code uses the list and calls the methods on IValidatableTable, you can use mocks:

var mockTbl = new Mock<IValidatableTable>();
// Add setups as needed

If - as you write - you want to add a real ValidatableTable, you can create and add it to your list:

tables.Add(new ValidatableTable());

On mocking the list

As mocking a list is a tedious process if you look at the number of members and their character (e.g. enumerator support and so on), you can also check the list after you have run your test whether the items have been changed in the way you expect, e.g.:

  • Does the length meet your expectations?
  • Have new items been added with the expected data?
  • Have items been removed that should have been removed?

Look at it from a test perspective: is it important to you that items are added using Add or is it ok if the code is later changed to use AddRange to add items more efficiently?

When checking the list after the code under test has been run, you find out relevant changes (and the test will only fail if the result does not match your expectations). In contrast, if you mock the list, you "micro-test" the way, how the list has been used in the code. It will fail when a list-method has been called in an unexpected way. IMO this will lead to irrelevant test failures. Hence, I'd prefer to not mock the list in the majority of the cases.

CodePudding user response:

One of the constructor overloads for Mock accepts an array of arguments to pass to the mocked type's constructor, so if it's possible to use a List<ValidatableTable> instead of an IList<ValidatableTable>, you could do this:

var constructorArgs = new List<ValidatableTable> 
{ 
    //Your "real instance"
    new ValidatableTable(),
};

var myMock = new Mock<List<ValidatableTable>>(constructorArgs);

But at this point, I'd question the usefulness of mocking a List at all since there's no "behaviour" that you can really change - all you can do is control the contents and that doesn't feel like something you need a Mock for.

  • Related