0

我有使用 MoQ 创建部分存根的代码。我更喜欢与接口交互而不是具体实现,这样如果我有不同的接口实现,我就不必修改单元测试。

例如,我有一个工厂方法,例如:

private Mock<ISomeInterface> ISomeInterfaceStubFactory()
{
    return new Mock<SomeConcreteImplementation>();
}

下面是调用该方法的代码:

var partialStub = ISomeInterfaceStubFactory();            
partialStub.Setup(m => m.MethodToStubOutThatMethodToTestCalls(It.IsAny<string>())).Returns(new List<SomeOtherObject>());
partialStub.CallBase = true;

var actualResult= partialStub.Object.MethodToTest();

Assert.That(actualResult, Is.EqualTo(expectedResult));

问题是这样做时 ISomeInterfaceStubFactory 不会编译。所以我将其更改为如下所示,但这样做似乎会破坏部分存根。实际实现的MethodToStubOutThatMethodToTestCalls操作被调用,而不是存根版本。基本上我正在尝试对存根对象使用多态性。有没有办法做到这一点?我希望我的单元测试不会与具体实现高度耦合。

private Mock<ISomeInterface> ISomeInterfaceStubFactory()
{
    return new Mock<SomeConcreteImplementation>.As<ISomeInterface>();
}
4

2 回答 2

2

我认为你错过了模拟对象的意义。从具体实现返回模拟是没有意义的。这个想法是让被测试的类依赖于你可以模拟的一些接口或抽象。

于 2010-10-08T18:28:13.230 回答
0

根据您的说明修改我的答案。我不反对 arootbeer,但我确实想了解您在做什么以及为什么它不起作用。

这是我认为您正在尝试做的一个简单示例。两种具体实现的测试都通过了我。这是你想要做的,这个例子对你有用吗?

接口和类:

using System;

namespace ClassLibrary1
{
    public interface IFoo
    {
        string GetBaseString();
        string GetExtendedString();
    }
    public class Foo_A : IFoo
    {
        public virtual string GetBaseString()
        {
            return "Foo_A";
        }
        public virtual string GetExtendedString()
        {
            return GetBaseString() + "_Bar";
        }
    }
    public class Foo_B : IFoo
    {
        public virtual string GetBaseString()
        {
            return "Foo_B";
        }
        public virtual string GetExtendedString()
        {
            return GetBaseString() + "_Bar";
        }
    }
}

单元测试:

using System;
using Xunit;
using Moq;

namespace ClassLibrary1.UnitTests
{
    public class Class1
    {
        [Fact]
        public void GetExtendedString_ReturnsExtendedString()
        {
            var partialFoo = IFooFactory();

            partialFoo.Setup(x => x.GetBaseString()).Returns("Foo");
            partialFoo.CallBase = true;

            string result = partialFoo.Object.GetExtendedString();

            Assert.Equal("Foo_Bar", result);
        }

        private Mock<IFoo> IFooFactory()
        {
            return new Mock<Foo_A>().As<IFoo>();
            //return new Mock<Foo_B>().As<IFoo>();
        }
    }
}
于 2010-10-10T18:16:31.680 回答