2

CSV を解析する C# アプリケーションの単体テストを行っています。try/catch ブロックを強制的に失敗させることはできないため、コード カバレッジは 94% です。Nuget http://joshclose.github.io/CsvHelperの CsvHelper を使用しています。

public void ParseCsv([FromBody] string csvText)
{
    var parseCsv = new XsvData(new[] { "\t", "," });
    try
    {
        using (var reader = new XsvReader(new StringReader(csvText)))
        {
            parseCsv.Read(reader, headerExists: true);
        }
    }
    catch (Exception)
    {
        var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
        {
            Content = new StringContent("Unable to read CSV."),
            ReasonPhrase = "Invalid CSV"
        };

        throw new HttpResponseException(response);
    }
}

考えられる最もあいまいな文字列を渡そうとしましたが、これを通過し、後で関数でエラーが発生します..

[TestMethod]
//[ExpectedException(typeof(HttpResponseException))]
public void TestUploadCsv_UploadingCsvNonCsv()
{
    const string csvText = "fhfhk@- jhjfh@ajh- fjkqeqir%hjewq@hf- ujewqh$phfuw \n hfwu- ihfq&if*u@q- afuhwu- fhiue@wfhiuewhiuf";
    var context = GetMyFakeEntityDatabase();
    var controller = new MyController(context);
    controller.ParseCsv(csvText);
}

try/catch ブロックの後に、すべてのヘッダーが存在することを強制するセクションがあり、そこで失敗しますが、この例では、読み取り中に失敗するはずです。単体テストを強制的に失敗させるにはどうすればよいですか? どんな助けでも大歓迎です!前もって感謝します。

4

3 に答える 3

0

具象型の代わりにプロバイダー パターンとインターフェイスを使用し、例外をスローするモック オブジェクトに置き換えて単体テストを実行します。

詳細に:

  • IXsvReaderからインターフェースを抽出XsvReader
  • IXsvReaderで例外をスローする の新しい具象インスタンスを実装しますRead。個別に処理することが予想されるエラーごとに 1 つの具象実装クラスを作成します (この場合、必要なのは 1 つだけです)。
  • メソッドを含むクラスには、設定可能ParseCSVな のプロパティがあります。IXsvProvider同じクラスのコンストラクターで、そのプロパティを「実際の」リーダーを返す既定のプロバイダーに設定します。このインターフェイスにはメソッドが 1 つしかありません。GetXsvReader(string text)
  • テスト クラスで、ParseCSV 関数を使用してクラスを新規作成しIXsvReader、メソッドを使用しようとするたびに単に例外をスローする「ダミー」を返す IXsvProvider(s) を挿入します。
于 2014-10-01T16:03:45.647 に答える
0

You should use Inversion of Control and inject the dependency into the controller instead of creating it in controller action. This way you can mock out the reader, and have it throw an except instead.

I'm going to write this example in terms of CsvHelper since that's what you say you are using, even though the example doesn't look like it.

Roughly:

public class MyController : Controller
{
    private readonly ICsvReader csv;

    public MyController( ICsvReader csv )
    {
        this.csv = csv;
    }
}

public class CsvReaderMock : ICsvReader
{
    public void Read()
    {
        throw new Exception();
    }
}

Now you can use your mock ICsvReader when testing, and it will throw an exception.

Also, you should only ever test a single method. If your method has dependencies, you should be passing them in instead of creating them, so you can test only the code in that method, and not of the classes it creates.

于 2014-10-01T20:49:59.297 に答える
0

コメントで推奨されているjuharrのように、nullを渡すだけでこれを解決しました。

于 2014-10-28T20:49:59.527 に答える