3
votes

I am new to MoQ framework. I am writing unit testing for controller using MoQ framework and here is my test method,

var mockedItemDetail = new ItemDetail()
        {
            Name = null
        };

        var mockObject = new Mock<IItem>();
        mockObject.Setup(x => x.GetItemDetail()).Returns(mockedItemDetail);

        var result = myController.GetDetails() as ViewResult;

Here is my Controller Method,

public ActionResult GetDetails()
    {
        var controllerItemDetail = new ItemDetail();
        controllerItemDetail = _item.GetItemDetail();
        controllerItemDetail.Name = "Changed Name";
        return View("ViewName", controllerItemDetail);
    }

Test runs and now I want to assert the sent mockedItemDetail and received model result controllerItemDetail.

In above case, mockedItemDetail property "Name" has null and received controllerItemDetail property Name as "Changed Name".

But whenever I debug, after calling the test method GetDetails(),

  1. My mockedItemDetail property Name is also updated as "Changed Name" in the current scope and I don't know why? Is this is the actual behavior of MoQ?

Edited Content

Consider the same above case in below mock list, here the change in the mock object will not update in all contexts. i.e. The list count for mockedItemDetailList remains 0 and the list count of controllerItemDetail is 1 even after test method calls. Why?

Test method:

var mockedItemDetailList = new List<ItemDetail>();

    var mockObject = new Mock<IItem>();
    mockObject.Setup(x => x.GetListOfItemDetail()).Returns(mockedItemDetailList);

    var result = myController.GetDetails() as ViewResult;

Controller method:

    public ActionResult GetDetails()
{
    var controllerItemDetail = new ItemDetail();
    controllerItemDetail = _item.GetListOfItemDetail();
    controllerItemDetail.Add(new ItemDetail(){
    Name = "Changed Name"
    });
    return View("ViewName", controllerItemDetail);
}
1
You're returning a specific object for x.GetItemDetail(). Why would it not update in the current context? That object is being modified at controllerItemDetail.Name = "Changed Name";. This is intended behavior.Goodbye StackExchange
Mockling is a sinMicky
Please find the edited content @FrankerZPraveen
Based on the code you've posted I agree with @FrankerZ, that is the intended behaviour (and it is also the expected behaviour in the 2nd example, both variables refer to the same instance of the list so the list should have an object added ). However it is hard to tell from your posted code how the mocked object(s) are injected into your controller. Are you passing the mocked object (IItem) into the constructor of your controller?Mats Björkman Eldh

1 Answers

2
votes

You have a very specific object:

var mockedItemDetail = new ItemDetail()
{
    Name = null
};

When you call mockObject.Setup(x => x.GetItemDetail()).Returns(mockedItemDetail);, you're returning the reference to mockItemDetail. Any changes on that object will update in all contexts.

A quick follow up. To have it return a blank new ItemDetail() each time, you can simply use the lambda method of Returns():

mockObject.Setup(x => x.GetItemDetail()).Returns(() => new ItemDetail()
{
    Name = null
});