Home > Net >  How to inherit one mock from another?
How to inherit one mock from another?

Time:03-23

Say i have this example code:

interface IBase {
    int BaseProperty { get; }
}
interface IDerived : IBase {
    int DerivedProperty { get; }
}

and i like to write mocks for both interfaces.

Base mock is easy:

class BaseMock : Mock<IBase> {
    public int BaseProperty { get; set; } = 42;
    public BaseMock() {
        SetupGet(o => o.BaseProperty).Returns(BaseProperty);
    }
}

but im not sure how to correctly write derived mock:

class DerivedMock : Mock<IDerived> {
    public int BaseProperty { get; set; } = 42;
    public int DerivedProperty { get; set; } = 73;
    public DerivedMock() {
        // setups related to IBase
        SetupGet(o => o.BaseProperty).Returns(BaseProperty);

        // setups related to IDerived
        SetupGet(o => o.DerivedProperty).Returns(DerivedProperty);
    }
}

this implementation will work as expected, but im forced to copy bassically whole content of BaseMock class here and that is not DRY ...

ideally i would like to inherit DerivedMock from BaseMock, but then setups related to IDerived would not compile (o is IBase and i it to be IDerived)...

I appreciate any kick in the right direction :)

CodePudding user response:

Rafał Rutkowski kicked me to right direction and i ended up with this code for anyone else interested:

interface IBase {
    int BaseProperty { get; }
}
interface IDerived : IBase {
    int DerivedProperty { get; }
}

class BaseMock : Mock<IBase>, IBase {
    public int BaseProperty { get; set; } = 42;

    public BaseMock() {
        SetupAll(this, this);
    }

    public static void SetupAll<TBase>([NotNull] Mock<TBase> mock, [NotNull] TBase instance)
        where TBase : class, IBase {
        mock.SetupGet(o => o.BaseProperty).Returns(instance.BaseProperty);
    }
}


class DerivedMock : Mock<IDerived>, IDerived {
    public int BaseProperty { get; set; } = 42;
    public int DerivedProperty { get; set; } = 73;

    public DerivedMock() {
        SetupAll(this, this);
    }

    public static void SetupAll<TDerived>([NotNull] Mock<TDerived> mock, [NotNull] TDerived instance) 
        where TDerived : class, IDerived {
        BaseMock.SetupAll(mock, instance);
        mock.SetupGet(o => o.DerivedProperty).Returns(instance.DerivedProperty);
    }
}

public class UnitTest1
{
    public void Test() {
        BaseMock baseMock = new BaseMock();
        IBase baseObject = baseMock.Object;

        baseMock.BaseProperty = 37;
        Assert.AreEqual(37, baseObject.BaseProperty);
        baseMock.VerifyGet(o => o.BaseProperty, Times.Never);
        
        // ----------------

        DerivedMock derivedMock = new DerivedMock();
        IDerived derivedObject = derivedMock.Object;

        derivedMock.BaseProperty = 42;
        derivedMock.DerivedProperty = 73;
        Assert.AreEqual(42, derivedObject.BaseProperty);
        Assert.AreEqual(73, derivedObject.DerivedProperty);
    }
}

reason why i wrote it this way is that i can dynamicall change property value AND verify that it was readed / written.

CodePudding user response:

You don't inherit from the Mock class. Instead you use Mock's Object property to get the mocked object. To reuse setting up IBase mock, you can do something like this:

    private static void SetupBase<T>(Mock<T> mock)
        where T : class, IBase
    {
        // setup base methods and properties
        mock.SetupGet(x => x.BaseProperty).Returns(1);
    }

    private static void SetupDerived(Mock<IDerived> mock)
    {
        SetupBase(mock);

        // setup derived methods and properties
    }

    [Test]
    public void Test()
    {
        var derivedMock = new Mock<IDerived>();
        SetupDerived(derivedMock);
        var derived = derivedMock.Object;

        Assert.AreEqual(1, derived.BaseProperty);

        derivedMock.SetupGet(x => x.BaseProperty).Returns(2);
        Assert.AreEqual(2, derived.BaseProperty);
    }
  • Related