如何从另一个模拟继承一个模拟?

发布于 2025-01-15 13:10:57 字数 1102 浏览 3 评论 0原文

假设我有这个示例代码:

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

并且我喜欢为两个接口编写模拟。

基本模拟很简单:

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

但我不确定如何正确编写派生模拟:

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);
    }
}

此实现将按预期工作,但我被迫在此处复制 BaseMock 类的基本全部内容,而这不是 DRY ...

理想情况下,我想从 BaseMock 继承 DerivedMock ,但是与 IDerived 相关的设置将无法编译(oIBase 和我它是IDerived)...

我很欣赏任何朝着正确方向的努力:)

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 :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若言繁花未落 2025-01-22 13:10:57

Rafał Rutkowski 把我踢向了正确的方向,我最终为其他感兴趣的人提供了这段代码:

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);
    }
}

我以这种方式编写它的原因是我可以动态更改属性值并验证它是否被读取/写入。

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.

拥抱我好吗 2025-01-22 13:10:57

您不是从 Mock 类继承的。相反,您可以使用 Mock 的 Object 属性来获取模拟对象。要重用设置 IBase 模拟,您可以执行以下操作:

    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);
    }

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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文