1. ホーム
  2. c#

[解決済み] メソッドをモックして例外をスローさせ(moq)、それ以外はモックされたオブジェクトのように動作させる?

2022-02-27 07:34:46

質問

私は 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 インタフェースは次のようになる。

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

実際のクラスでは System.IO.IOException が投げられたとき、その IFileConnection の具象クラスはリモートとの接続を失い、メールを送ったりしています。

私はMoqを使って Transfer クラスを作成し、それを具体的な Transfer を使用する場合を除いて、すべてのプロパティとメソッドで GetFile メソッドが呼び出されたときに System.IO.IOException を作成し Transfer クラスはそれを適切に処理します。

私はこの仕事に適したツールを使っているのだろうか? このやり方は正しいのだろうか? そして、そのユニットテストのためのセットアップをどのように書けばいいのでしょうか? NUnit ?

解決方法は?

このようにして、私がやろうとしていたことを実現することができました。

[Test]
public void TransferHandlesDisconnect()
{
    // ... set up config here
    var methodTester = new Mock<Transfer>(configInfo);
    methodTester.CallBase = true;
    methodTester
        .Setup(m => 
            m.GetFile(
                It.IsAny<IFileConnection>(), 
                It.IsAny<string>(), 
                It.IsAny<string>()
            ))
        .Throws<System.IO.IOException>();

    methodTester.Object.TransferFiles("foo1", "foo2");
    Assert.IsTrue(methodTester.Object.Status == TransferStatus.TransferInterrupted);
}

この方法に問題があれば、教えていただきたいです。他の回答では、私のやり方が間違っているようですが、これはまさに私がやろうとしていたことでした。