c# - 模拟一个抛出异常(moq)的方法,但在其他方面表现得像被模拟的对象?

标签 c# unit-testing mocking moq

我有一个 Transfer 类,简化后如下所示:

public class Transfer
{
    public virtual IFileConnection source { get; set; }
    public virtual IFileConnection destination { get; set; }

    public virtual void GetFile(IFileConnection connection, 
        string remoteFilename, string localFilename)
    {
        connection.Get(remoteFilename, localFilename);
    }

    public virtual void PutFile(IFileConnection connection, 
        string localFilename, string remoteFilename)
    {
        connection.Get(remoteFilename, localFilename);
    }

    public virtual void TransferFiles(string sourceName, string destName)
    {
        source = internalConfig.GetFileConnection("source");
        destination = internalConfig.GetFileConnection("destination");
        var tempName = Path.GetTempFileName();
        GetFile(source, sourceName, tempName);
        PutFile(destination, tempName, destName);
    }
}

IFileConnection 接口(interface)的简化版本如下所示:

public interface IFileConnection
{
    void Get(string remoteFileName, string localFileName);
    void Put(string localFileName, string remoteFileName);
}

真正的类应该处理 System.IO.IOExceptionIFileConnection 具体类失去与远程连接、发送电子邮件等时抛出的异常.

我想使用 Moq 创建一个 Transfer 类,并在所有属性和方法中将其用作我的具体 Transfer 类,除了 GetFile 方法被调用 - 然后我希望它抛出 System.IO.IOException 并确保 Transfer 类正确处理它。

我是否使用了正确的工具来完成工作?我这样做是对的吗?我将如何为 NUnit 编写该单元测试的设置?

最佳答案

这里是你如何模拟你的 FileConnection

Mock<IFileConnection> fileConnection = new Mock<IFileConnection>(
                                                           MockBehavior.Strict);
fileConnection.Setup(item => item.Get(It.IsAny<string>,It.IsAny<string>))
              .Throws(new IOException());

然后实例化您的 Transfer 类并在您的方法调用中使用 mock

Transfer transfer = new Transfer();
transfer.GetFile(fileConnection.Object, someRemoteFilename, someLocalFileName);

更新:

首先,您必须只模拟您的依赖项,而不是您正在测试的类(在本例中为传输类)。在你的构造函数中声明这些依赖关系可以很容易地看到你的类需要哪些服务来工作。它还可以在您编写单元测试时用假货替换它们。目前不可能用假货替换这些属性。

由于您使用另一个依赖项设置这些属性,我会这样写:

public class Transfer
{
    public Transfer(IInternalConfig internalConfig)
    {
        source = internalConfig.GetFileConnection("source");
        destination = internalConfig.GetFileConnection("destination");
    }

    //you should consider making these private or protected fields
    public virtual IFileConnection source { get; set; }
    public virtual IFileConnection destination { get; set; }

    public virtual void GetFile(IFileConnection connection, 
        string remoteFilename, string localFilename)
    {
        connection.Get(remoteFilename, localFilename);
    }

    public virtual void PutFile(IFileConnection connection, 
        string localFilename, string remoteFilename)
    {
        connection.Get(remoteFilename, localFilename);
    }

    public virtual void TransferFiles(string sourceName, string destName)
    {
        var tempName = Path.GetTempFileName();
        GetFile(source, sourceName, tempName);
        PutFile(destination, tempName, destName);
    }
}

这样你就可以模拟 internalConfig 并让它返回 IFileConnection 模拟来做你想做的事。

关于c# - 模拟一个抛出异常(moq)的方法,但在其他方面表现得像被模拟的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10323794/

相关文章:

javascript - 无法使用 JSON 将对象列表传递到 View

C++ : Is it possible to write Mock class for a class with parameterized constructor

java - 如何测试没有抛出异常?

java - 模拟 CountDownTimer 和 Handler

c# - 我如何使用 Caller Info 属性进行 TDD?

mocking - Dart 模拟 HTML 库

c# - 在 C# 中检查网站可用性

c# - .NET HashTable 与 Dictionary - Dictionary 能一样快吗?

c# - .NET:你能简化这个 Math.Ceiling 表达式吗

java - 如何使包私有(private)类仅对其他包可见?