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

本文关键字:调用 是否 DAMP 方法 检测 何使用 Microsoft Shims | 更新日期: 2023-09-27 18:05:24

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

这是在测试方法中设置shim的代码:

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

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

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

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

总是由ref传递,不会受到lambda的影响,甚至可能被认为比简单的布尔变量更具可读性。

添加积极的内联,ref参数或out参数不会使你的方法更潮湿。它只会把人搞糊涂:)。

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