Search code examples
c#unit-testingnunitnsubstitute

Mocked method returns null when using anonymous types


I have this code:

using NSubstitute;
using NUnit.Framework;
using System;
using System.Linq.Expressions;

namespace MyTests
{
    public interface ICompanyBL
    {
        T GetCompany<T>(Expression<Func<Company, T>> selector);
    }

    public partial class Company
    {
        public int RegionID { get; set; }
    }

    public class Tests
    {
        [Test]
        public void Test()
        {
            var companyBL = Substitute.For<ICompanyBL>();

            //Doesn't work
            companyBL.GetCompany(c => new { c.RegionID }).Returns(new
            {
                RegionID = 4,
            });

            //Results in null:
            var company = companyBL.GetCompany(c => new { c.RegionID });

            //This works:
            //companyBL.GetCompany(Arg.Any<Expression<Func<Company, Company>>>()).Returns(new Company
            //{
            //    RegionID = 4,
            //});

            //Results in non null:
            //var company = companyBL.GetCompany(c => new Company { RegionID = c.RegionID });
        }
    }
}

When I use this code, the company var is null. However, the commented out code works fine and results in a non null value.

Why does it not work with the anonymous type? Is there some way to get this to work with anonymous types?

NSubstitute version = 1.10.0.0.

.NET Framework version = 4.5.2.


Solution

  • Assuming that the previous options may not be desirable, another approach may be available to you, if you have access to the (in this case) source for CompanyBL.

    This alternative is to mark the methods needed to be mocked as virtual and have the mock inherit from the concrete class CompanyBL rather than implement the whole interface.

    The reason you may want to do this is to make the mock less fragile .. ie when someone extends the ICompanyBL interface they will not need to add implementations to the mock.

    While this is not an answer for specifically how to use NSubstitute I feel it is a worthwhile alternative. A variation may be to change CompanyBL to have protected virtual methods for functionality that needs to be replaced in the mock. Writing code that is more testable should be a concern which arguably merits these types of changes.