Moq - 使用通用函数设置模拟对象进行单元测试

时间:2015-09-21 22:20:07

标签: c# unit-testing generics moq dry

在我的单元测试中尝试遵循DRY(不要重复自己)原则我试图创建一个通用单元测试,它将对几个返回共享相同接口的对象的方法执行相同的测试。但是,我似乎无法找到一种方法来为泛型方法中的方法创建一个mock.Setup。示例如下:

以下是类实现:

public class RootClass
{
    public Foo Foo { get; set; }
}

public class Foo
{
    public Bar1 Method1(int x)
    {
        var bar = new Bar1();
        // do stuff //
        return bar;
    }
    public Bar2 Method2(string str)
    {
        var bar = new Bar2();
        // do stuff //
        return bar;
    }
}

public interface IBar
{
    string Message { get; set; }
    bool Success { get; set; }
    Exception ex { get; set; }
}

public class Bar1 : IBar
{
    public string Result { get; set; }
    public Exception ex { get; set; }
    public string Message { get; set; }
    public bool Success { get; set; }
}

public class Bar2 : IBar
{
    public int Result { get; set; }
    public Exception ex { get; set; }
    public string Message { get; set; }
    public bool Success { get; set; }
}

以下是测试实施:

private static RootClass systemUnderTest;
private static Mock<IFoo> FooMock;

[TestInitialize]
public void Setup()
{
    FooMock = new Mock<IFoo>();
    systemUnderTest = new RootClass();
    systemUnderTest.Foo = FooMock.Object;
}

[TestMethod]
public void Method1_Bar1SuccessIsTrue()
{
    //FooMock.Setup(x => x.Method1(It.IsAny<int>())).Returns(new Bar1);    <~~~~This is the Moq Setup I would like to move into the generic method
    AssertBarSuccessIsTrue<int, Bar1>(systemUnderTest.Bar1, FooMock.Object.Bar1);
}

[TestMethod]
public void Method2_Bar2SuccessIsTrue()
{
    //FooMock.Setup(x => x.Method2(It.IsAny<string>())).Returns(new Bar2);
    AssertBarSuccessIsTrue<string, Bar2>(systemUnderTest.Bar2, FooMock.Object.Bar2)
}

private void AssertBarSuccessIsTrue<PARAM, BAR>(Func<PARAM, BAR> f, Func<PARAM, IBAR> task) where BAR : IBAR where PARAM : new()
{
    FooMock.Setup(x => task);  <~~~Throws an ArgumentException; no doubt because of the missing lambda expression.
    PARAM parameter = new PARAM();
    BAR bar = f.Invoke(parameter);
    Assert.IsTrue(bar.Success);
}

我试图通过多次尝试来完成这项工作,包括为lambda表达式创建一个参数,为It.IsAny&lt;&gt;()表达式创建一个参数,为测试中的指定方法创建委托。但是,每次尝试都会产生编译器错误或引发运行时异常。

如果我在每个测试中进行设置,我可以创建通用测试(如注释掉的.Setup行中所示)。但是,是否有人知道如何将该设置行移动到通用方法中?我知道它只有一行,但在我看来这应该是可能的。

0 个答案:

没有答案