Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单元测试:检查是否正在调用方法_C#_Unit Testing - Fatal编程技术网

C# 单元测试:检查是否正在调用方法

C# 单元测试:检查是否正在调用方法,c#,unit-testing,C#,Unit Testing,我有以下课程: public class MyClass { public void MyMethod() { try { ... save data to file ... } catch (Exception exception) { ErrorDisplay.ShowErrorMessage("My

我有以下课程:

public class MyClass
{
    public void MyMethod()
    {
        try
        {
            ...
            save data to file
            ...
        }
        catch (Exception exception)
        { 
            ErrorDisplay.ShowErrorMessage("MyMethod", exception);
        }
    }
}

public class ErrorDisplay
{
    public static ShowErrorMessage(string methodName, Exception exception)
    {
        if (exception is IOException)
            MessageBox.Show(methodName + " : " + GetIODisplayMessage());
        else if ... 
            ...
        else
            ...
   }

    public static string GetIODisplayMessage()
    {
        return "IO error";
    }

    ....
}
我需要在witch中编写一个单元测试,我将模拟IOException,我需要检查它 正在调用方法。有没有办法测试是否调用了一个方法? 或者是关于如何为我的案例进行单元测试的另一个想法


谢谢

测试静态方法很难。可以考虑将方法更改为非静态的。如果使用依赖项注入,这会容易得多。另一个选择是为商业TypeMock库购买许可证,该库允许您通过修改IL代码来模拟静态方法。这允许您编写代码来验证方法是否被调用、参数是什么等。

您应该使用Moq或Rhino mock之类的模拟库 看看这个

对于静态方法,您可以使用


但是不是免费的

您不能直接检查是否调用了一个方法,但是您可以将MyMethod中的主体提取到实现接口的单独类中,然后使用一些类似Rhinomock的模拟库来注入行为


使用RhinoMock,您可以指示mock抛出异常并期望调用

取决于您的模拟框架。没有一个免费的(Rhino、Moq)允许您对静态方法设定期望值。您需要购买一个商业产品,如Typemock或更好的产品,使ErrorDisplay类上的方法成为虚拟的,并将其实例传递给MyClass


例如,如果使用Moq,您可以发送一个
Mock
实例,并对其设置期望值。

如上所述,使用静态ErrorDisplay会导致在IErrorDisplay实现中进行测试和注入时出现许多问题,这将解决其中一些问题,但不是全部问题(请参阅下面的MessageBox)。然而

静态+接口 如果您需要保留静态类ErrorDisplay,并且不想为TypeMock提供支持,那么可以添加一个间接级别

public interface IDisplayErrorImplementation {
    void ShowErrorMessage(string message, Exception ex);
}

public class DefaultDisplayErrorImplementation : IDisplayErrorImplementation {
    public void ShowErrorMessage(string message, Exception ex) {
        //...
    }
}

public static class DisplayError {
    static DisplayError(){
        Implementation = new  DefaultDisplayErrorImplementation();
     }

    public static IDisplayErrorImplementation Implementation { get; set;}

    public static void ShowErrorMessage(string message, Exception ex) {
        Implementation.ShowErrorMessage(message, ex);
    }
}
您可以保留对ErrorDisplay的现有调用,但它们现在更易于替换和测试

这不是一个完美的解决方案,但是,如果维护遗留代码,它可以让您添加一些可测试性,而无需进行重大的返工

对话框 在ErrorDisplay上运行单元测试还有一个问题;您将出现一个消息框。如果尝试在测试工具(或作为构建的一部分)中运行测试,则不太好

再说一次,间接是你的朋友。您可以将MessageBox.Show()调用替换为对MessageDisplayService.Show()的调用。默认实现可以调用消息框,一个虚拟的消息框可以用于测试(模拟或简单的不做任何事情实现)

单元测试 测试的单元边界是什么

从问题中可以看出,您希望对MyClass::MyMethod()运行测试,导致IOException并查看是否调用了GetIioSplayMessage()。如果我理解错误,请跳过下一节:)

您是否计划对可能发生IOException的每个类/方法执行此操作? 您是否计划对ErrorDisplay处理的每个其他异常类型可能发生的每个类/方法执行此操作

这是一项大量的工作,只需一次又一次地重新测试ErrorDisplay代码

我会看到的界限是

MyClass::MyMethod

如果发生异常,它将调用ErrorDisplay.阵雨RorMessage()并传入“MyMethod”和异常

之后的任何事情都是它无法控制的,不应该成为单元测试的一部分

错误显示。错误消息()

如果使用IOException调用它,那么它将显示通过调用GetIioSplayMessage()获得的消息

这独立于调用代码(如上所述),可以单独进行单元测试

ErrorDisplay.GetIODisplayMessage()

返回正确的错误消息。好的,如果该值是硬编码的,但显示了原理,则有点过头了

在测试MyClass::MyMethod时,我们希望验证当发生异常时,调用错误显示代码并传递正确的方法名和异常

在测试ErrorDisplay.阵雨RorMessage()时,我们验证是否为调用MessageDisplayService.Show()的异常类型获得了正确的消息 methodname+“:”+ 我们不需要在这里测试IioSplayMessage的文本

测试ErrorDisplay.GetIioDisplayMessage()时,我们会检查它是否返回正确的消息

希望这是有用的


Alan。

您应该避免使用静态类,而应该使用IoC和依赖项注入类型,因为它可以与静态方法一起工作。谢谢您的回答。这真的很有用。