Странное поведение с NUnit, ExpectedException и доходностью - PullRequest
8 голосов
/ 26 ноября 2011

У меня странное поведение в тестах, где я хочу проверить, что возникает исключение, когда в качестве параметра передается значение 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);
        }
    }
}

Есть ли логическое объяснение этому поведению, и я должен сделать мою реализацию по-другому?

1 Ответ

9 голосов
/ 26 ноября 2011

Причиной такого поведения является ключевое слово yield. При использовании yield компилятор сгенерирует класс для метода с yield в нем. При вызове этого метода управление безоговорочно возвращается обратно вызывающей стороне. Ничто в вашем методе на самом деле не выполняется до того, как это потребуется.

Если вы извлечете оператор использования в отдельный метод и вернете результат, ваш тест пройдет успешно. Или вы можете сохранить результат в переменной в вашем тесте, и, например, вызвать 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);
            }
        }
    }
...