Artem
Artem

Reputation: 2314

Mocking objects with different constructors

I am trying to understand why mocking behaves in such a way (I'm using NUnit with Moq). Let's say, we have a simple class:

public class Package
{
    public virtual int PackageId { get; set; }

    public Package()
        :this(-1)
    {
    }

    public Package(int packageId)
    {
        PackageId = packageId;
    }
}

And some simple tests to discuss:

[TestFixture]
public class NUnitTrickyTest
{
    private const int SamplePackageId = 10;

    [Test]
    public void TestPackageSetUp_WhenMockedWithDefaultConstructor_ExpectSamplePackageIdSet()
    {
        var samplePackage = new Mock<Package>();

        samplePackage.SetupProperty(x => x.PackageId, SamplePackageId);

        Assert.AreEqual(SamplePackageId, samplePackage.Object.PackageId);
    }

    [Test]
    public void TestPackageSetUp_WhenMockedWithParametrizedConstructor_ExpectSamplePackageIdSet()
    {
        var samplePackage = new Mock<Package>(SamplePackageId);

        // samplePackage.SetupProperty(x => x.PackageId, SamplePackageId);

        Assert.AreEqual(SamplePackageId, samplePackage.Object.PackageId);
    }
}

The first test fails as samplePackage.Object.PackageId returns -1, not 10 as expected. As I understand mocked Package() calls parameterized constructor which initializes the property with default -1. In the second test we find samplePackage.Object.PackageId returning 0.

The first thing I don't understand why 0 was returned (in debug I saw that 10 was passed in the constructor, but the property remained 0 value). The second one: if we uncomment this command samplePackage.SetupProperty(x => x.PackageId, SamplePackageId) in the second test, it will succeed. So why SetupProperty behaves as expected in that case (property returns 10), and not in such a way in the first test?

Could you please help? This is my first post so don't be severe :)

Upvotes: 2

Views: 300

Answers (1)

Justin Pihony
Justin Pihony

Reputation: 67115

All mockable (virtual) methods use a proxy by default, so that is why you get a default value (0) on the second test (the proxy is not set). You can get around this by setting CallBase = true on your mock, though.

CallBase = true will use default implementations if available instead of trying to mock everything out.

It took me a second to figure out the reason for the first one failing and I believe that this is because SetupProperty only turns on tracking with a default value and since you are overriding that default value in the constructor then that is what is used. If you want to force a value then you need to use Setup(x=>x.PackageId).Returns(SamplePackageId) or SetupGet

Upvotes: 7

Related Questions