9

null がパラメーターとして渡されたときに例外がスローされることをテストしたいテストで奇妙な動作があります。テストを実行すると、NUnit から取得されます。

    System.ArgumentNullException was expected
    -- Exception doesn't have a stack trace -- 

私のテスト:

[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void Should_not_retrieve_any_fields_when_file_is_null()
{
    _creator.CreateFields(null);
}

私の実装:

public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file)
{
    if (file == null) throw new ArgumentNullException("file");

    using (var reader = new StreamReader(file.InputStream))
    {
        var firstLine = reader.ReadLine();
        var columns = firstLine.Split(new[] { ',' });

        for (var i = 0; i < columns.Length; i++)
        {
            yield return new ImportField(columns[i], i);
        }
    }
}

この動作には論理的な説明がありますか?実装を別の方法で行う必要がありますか?

4

1 に答える 1

10

この動作が発生する理由は、yield キーワードが原因です。yield を使用する場合、コンパイラは、yield を含むメソッドのクラスを生成します。そのメソッドを呼び出すと、制御は無条件に呼び出し元に戻されます。メソッドが必要になる前に実際に実行されるものは何もありません。

using ステートメントを別のメソッドに抽出して結果を返すと、テストは成功します。または、結果をテスト内の変数に格納して、たとえば "ToList()" を呼び出すこともできます。

    public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file)
    {
        if (file == null) throw new ArgumentNullException("file");

        return ExtractFromFile(file);
    }

    private IEnumerable<ImportField> ExtractFromFile(HttpPostedFileBase file)
    {
        using (var reader = new StreamReader(file.InputStream))
        {
            var firstLine = reader.ReadLine();
            var columns = firstLine.Split(new[] { ',' });

            for (var i = 0; i < columns.Length; i++)
            {
                yield return new ImportField(columns[i], i);
            }
        }
    }
于 2011-11-26T19:51:51.447 に答える