简体   繁体   English

NUnit,ExpectedException和yield return的奇怪行为

[英]Strange behavior with NUnit, ExpectedException & yield return

I have a strange behavior in a tests where I want to test that an exception is thrown when null is passed in as a parameter. 我在测试中有一个奇怪的行为,我想测试当作为参数传入null时抛出异常。 When I run the test I get from NUnit: 当我运行测试时,我从NUnit获得:

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

My test: 我的测试:

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

My implementation: 我的实施:

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);
        }
    }
}

Is there a logical explanation to this behavior and should I make my implementation differently? 这种行为是否有合理的解释,我应该以不同的方式实现我的实现吗?

The reason you're getting this behaviour is because of the yield keyword. 您获得此行为的原因是yield关键字。 When using yield, the compiler will generate a class for the method with the yield in it. 使用yield时,编译器将为该方法生成一个类,其中包含yield。 When calling that method, control is unconditionally returned to back to the caller. 调用该方法时,无条件地将控制权返回给调用者。 Nothing in your method is actually executed before it is need. 您的方法中的任何内容都不会在需要之前执行。

If you extract your using statement into a separate method and return the result, your test will pass. 如果将using语句提取到单独的方法中并返回结果,则测试将通过。 Or you can store the result to a variable in your test, and for example call "ToList()" on it. 或者,您可以将结果存储到测试中的变量中,例如,在其上调用“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);
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM