pampua84
pampua84

Reputation: 874

C# Moq framework return null reference not correct object

i have a problem in unit test, i use moq framework to mock my database interface to returns dataset. The problem is that when i call BLL methods it returns null instead the object i setted. The BLL code is:

public ApplicationsManager(IApplicationsManagerDal applicationsManagerDal)
{
    _applicationsManagerDal = applicationsManagerDal ?? throw new Exception("applicationsManagerDAL is null");
}

public IpApplication AddIpApplication(IpApplication ipApplication)
{

    try
    {
        if (Validator.ExecuteValidation(ipApplication, new AddIpApplicationValidationRules()).ValidationFailures != null)
            return ipApplication;

        ipApplication = _applicationsManagerDal.AddIpApplication(ipApplication);

        ipApplication.Status = CommonStatus.OperationOk;
        }
        catch (BaseException e)
        {
            ipApplication.Status = e.Status;
        }
        catch (Exception e)
        {
            ipApplication.Status = ExceptionHandler.SetStatusForException();

            NLogger.LogException("IpApplication Name:" + ipApplication.Name, e);
        }

        return ipApplication;
    }

The code where i setted moq is:

var _mock = new Mock<IApplicationsManagerDal>();

_mock.Setup(a => a.AddIpApplication(new IpApplication
{
   Code = new Guid("00000000-B935-4E12-9037-000000000000"),
   Name = "APPLICATION_ZERO"
}))
.Returns(() => new IpApplication
{
    Code = new Guid("9631E691-B935-4E12-9037-2E874DB15B0D"),
    Description = "Test application",
    Enabled = true,
    Name = "APPLICATION_ZERO",
});

and the unit test is:

[TestMethod(), TestCategory("Unit")]
public void AddIpApplication_ValidRequest_IpApplicationSuccessfullyAdded()
{
    // Arrange
    _ipApplication = new IpApplication
        {
            Code = new Guid("9631E691-B935-4E12-9037-2E874DB15B0D"),
            Name = "APPLICATION_ZERO"
        };

    // Act AddIpApplication
    _ipApplication = _applicationManager.AddIpApplication(_ipApplication);

    Assert.IsTrue(_ipApplication.Code != Guid.Empty);
}

When the test call the BLL methods arrived at line:

ipApplication = _applicationsManagerDal.AddIpApplication(ipApplication);

it return always null. Can you explain me why? How can i get setted value or how i can change the unit test? Thank you and sorry for my bad english

Upvotes: 2

Views: 2366

Answers (2)

Nkosi
Nkosi

Reputation: 246998

When a mock is not invoked exactly as it was setup it will not behave as expected.

In your case you are passing a different instance/reference to the mock than what was used in the setup of the mock. This will cause the mock to return null (default behavior) when invoked.

For more flexibility where passes parameters are concerned you can use It.IsAny<IpApplication>() to accept any argument along with a Callback to set the desired properties on the provided argument. That should allow the method under test to be exercised with the provided mock.

_mock
    .Setup(_ => _.AddIpApplication(It.IsAny<IpApplication>()))
    .Callback((IpApplication arg) => { //<-- use call back to modify the provided parameter
        arg.Code = new Guid("9631E691-B935-4E12-9037-2E874DB15B0D");
        arg.Description = "Test application";
        arg.Enabled = true;
        arg.Name = "APPLICATION_ZERO";
    })
    .Returns((IpApplication arg) => arg); //<-- return provided parameter after Callback

//inject the mock into the subject under test.
_applicationManager = new ApplicationsManager(mock.Object);

Reference Moq Quickstart to get more details on how to use the framework.

Upvotes: 2

Owen Pauling
Owen Pauling

Reputation: 11841

The problem is that the IpApplication instance you use in the Setup references a different object to the one you are passing in during execution so the setup conditions do not match.

_mock.Setup(a => a.AddIpApplication(new IpApplication
{
   Code = new Guid("00000000-B935-4E12-9037-000000000000"),
   Name = "APPLICATION_ZERO"
}))

You can either override the equality methods of the particular class or change the logic in your Setup e.g.:

_mock.Setup(a => a.AddIpApplication(It.Is<IpApplication>(i => i.Code == expectedGuid && i.Name = expectedString))

Or use It.IsAny<IpApplication>() if you don't really care about the exact values.

Upvotes: 0

Related Questions