如何使用Microsoft Shims检测方法调用是DAMP

时间:2014-05-28 07:49:55

标签: c# unit-testing lambda

我遇到了编写一些单元测试的以下问题。我想测试是否在SUT中调用了类的方法。我使用Microsoft Shims,因为该方法属于一个不实现任何接口的类(Stubs不能使用)。填充程序拦截方法调用并将变量设置为true为lambda。变量在lambda之外定义,但在相同的范围内,因此捕获变量。当我尝试使用具有描述性名称的函数将代码重构为DAMP(描述性和有意义的短语)来包装填充程序创建,以及lambda时,问题就出现了。我被迫将变量传递给函数,然后让lambda捕获它,但这会导致变量的更改被限制在函数的范围内。我无法在参数上使用ref,因为我收到错误。我试图使用积极的内联自定义属性强制内联函数,但没有任何成功。由于C#不支持宏,我怎么能将DAMP限制在一个函数中,而不是将它放在单元测试代码中使它变得非常难以理解?

这是在测试方法中使用垫片设置的代码:

[TestMethod]
public void ATestMethod()
{
    //Arrange the test...
    bool myMethodHasBeenCalled = false;

    using (ShimsContext.Create())
    {
        ShimMyClass.AllInstances.MyMethod = 
        (x) => { 
            myMethodHasBeenCalled = true; 
        };

        //Act...
    }

    Assert.IsTrue(myMethodHasBeenCalled);
}

这就是我想要的代码......

private void DetectIfMyMethodHasBeenCalled(bool flag)
{
    ShimMyClass.AllInstances.MyMethod =
    (x) =>
    {
        flag = true;
    };
}

[TestMethod]
public void ATestMethod()
{
    //Arrange the test...
    bool myMethodHasBeenCalled = false;

    using (ShimsContext.Create())
    {
        DetectIfMyMethodHasBeenCalled(myMethodHasBeenCalled);

        //Act...
    }

    Assert.IsTrue(myMethodHasBeenCalled);
}

1 个答案:

答案 0 :(得分:4)

传入一个包含布尔参数的非常简单的类,而不是传递一个布尔参数。

public class MethodTracer{
    public bool WasCalled{ get; set; }
}

这将始终由ref传递,不会受到有趣的lambda技巧的影响,甚至可能被认为比简单的布尔变量更具可读性。

添加积极的内联,ref参数或out参数不会使您的方法更多DAMP。这只会让人们感到困惑:)。

[TestMethod]
public void ATestMethod()
{
    //Arrange the test...
    MethodTracer tracer = new methodTracer();

    using (ShimsContext.Create())
    {
        ShimMyClass.AllInstances.MyMethod = _ => { tracer.WasCalled = true; };

        //Act...
    }

    Assert.IsTrue(tracer.WasCalled);
}

或者让你的方法实际返回跟踪器:

private MethodTracer DetectIfMyMethodHasBeenCalled()
{
    MethodTracer tracer = new MethodTracer();

    ShimMyClass.AllInstances.MyMethod = _ => { tracer.WasCalled = true; };

    return tracer;
}

进行测试:

[TestMethod]
public void ATestMethod()
{
    using (ShimsContext.Create())
    {
        var myMethodCallTracer = DetectIfMyMethodHasBeenCalled();
        Assert.IsTrue(myMethodCallTracer.WasCalled);
    }
}