javirs
javirs

Reputation: 1100

Cannot initialize member of mocked class

I have an interface that has members, something like this:

public interface IDataLoader
{
    //other stuff
    // tools for loading the items to be processed from disk or cloud
    CustomCollection ItemsToBeProcessed {get; set;}
}

I'm doing UTs for other components of the system that consume those ItemsToBeProcessed and I want to avoid the complexity and dependencies for the loading.

In every UT I want to fill the ItemsToBeProcessed with specific hardcoded data. Then feed the data to the module being tested (the processor module) and compare the output with specific hardcoded expected data.

My problem is that I cannot initialize this ItemsToBeProcessed and I don't get why.

This is my UT so far:

[Test]
public void DataProcessor_TestData1_asExpected()
{
    Mock<IDataLoader> mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
    MainController.Loader = mokedAmplifier.Object;
    if(MainController.Loader.ItemsToBeProcessed == null)
        MainController.Loader.ItemsToBeProcessed = new CustomCollection();

    // here the MainController.Loader.ItemsToBeProcessed is still null.. why???

    var TestData = LoadTestData("testData1.xml");
    var ExpectedData = LoadExpectedData("ExpectedData1.xml")

    MainConroller.Loader.ItemsToBeProcessed.AddRange(TestData);

    var ProcessingModuleBeingTested = new ProcessingModule();
    var results = ProcessingModuleBeingTested.Process(MainController.Loader.ItemsToBeProcessed);
    Asert.isEqual(ExepctedData, results);
}

Ho do I initialize this member?

Upvotes: 2

Views: 342

Answers (3)

Nkosi
Nkosi

Reputation: 247571

Mock the desired member to return a usable object when invoked.

var collection = new CustomCollection();
var mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);

mokedAmplifier.Setup(_ => _.ItemsToBeProcessed).Returns(collection);

//...

If you want the mock to remember changes made to the property then use SetupAllProperties

Specifies that the all properties on the mock should have "property behavior", meaning that setting its value will cause it to be saved and later returned when the property is requested. (this is also known as "stubbing"). The default value for each property will be the one generated as specified by the Moq.Mock.DefaultValue property for the mock.

var mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);

mokedAmplifier.SetupAllProperties(); //<--

MainController.Loader = mokedAmplifier.Object;

if(MainController.Loader.ItemsToBeProcessed == null)
    MainController.Loader.ItemsToBeProcessed = new CustomCollection();

//...

Reference Moq Quickstart to get a help understanding the mocking framework.

Upvotes: 3

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37113

A property is nothing but a get- and a set-method. If you´d assign a value to your mocked instance, your just using the setter-method, which is in no way related to the getter-method. So by thefault Mock create a class similar to the following for you:

class TheMockClass : IDataLoader
{
    CustomCollection get_ItemsToBeProcessed { return whatever; }
    void set_ItemsToBeProcessed {  }
}

if you assign something to an instance of this class nothing would happen, as the setter does absoluetely nothing (not sure about the concrete internals, but important is that even if the setter does anything, it has nothing to do with what is being used within the getter).

You see that when being mocked those two methods don´t have anything in common. So you´d have to mock synchronously. However usually it´s enough to mock the getter to return your value, as you just use the value being mocked, not set it.

mokedAmplifier.Setup(_ => _.ItemsToBeProcessed).Returns(new CustomCollection());

Upvotes: 2

Pablo notPicasso
Pablo notPicasso

Reputation: 3161

You need to setup property:

    mokedAmplifier.SetupAllProperties();
    MainController.Loader = mokedAmplifier.Object;
    if (MainController.Loader.ItemsToBeProcessed == null)
        MainController.Loader.ItemsToBeProcessed = new CustomCollection();

or

    var coll = new CustomCollection();
    mokedAmplifier.Setup(x => x.ItemsToBeProcessed).Returns(coll);

Upvotes: 1

Related Questions