使用NUnit测试适配器进行单元测试失败,但在VS2012中无法使用ReSharper进行单元测试

时间:2013-06-28 12:00:34

标签: unit-testing visual-studio-2012 nunit resharper

我在VS2012中运行单元测试时出现了一个奇怪的问题。我正在使用NUnit并使用ReSharper运行它们,所有测试都在运行。但是当我的同事运行测试时,他们中的一些人没有ReSharper,所以他们使用的测试资源管理器扩展名为 NUnit测试适配器(Beta 3)v0.95.2 http://visualstudiogallery.msdn.microsoft.com/6ab922d0-21c0-4f06-ab5f-4ecd1fe7175d) 。然而,对于该扩展,一些测试失败了。

失败的具体代码如下:

public void Clear()
{
    this.Items.ForEach(s => removeItem(s));
}

    private bool removeItem(SequenceFlow item)
    {
        int i = this.Items.IndexOf(item);
        if (i == -1)
            return false;
        this.Items.RemoveAt(i);
        return true;
    }

例外是:

System.InvalidOperationException : Collection was modified; enumeration operation may not execute.
Result StackTrace:  
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.ForEach(Action`1 action)

现在,我不是在寻找答案,为什么我会遇到此异常,确定我能理解为什么会失败。但我无法理解的是,为什么测试失败了Test Exporer而不是使用ReSharper时。为什么我会为测试获得不同的行为?

在测试这两种情况时,我使用ildasm.exe查看代码是否编译方式不同,但IL代码是相同的。

测试也在我们的Team City服务器上提交期间运行,没有错误。

此外,在调试测试时,我在通过NUnit测试适配器进行调试时得到了相同的异常,但是在调试和使用ReSharper调试代码时,没有任何例外。

1 个答案:

答案 0 :(得分:1)

我发现在VS2012中,类似的代码在运行时会因同样的错误而失败。如果您在应用程序中使用此方法,它会成功吗?

您正在功能上迭代集合并在您仍在集合中时从中删除项目 - 这会更改集合的内部索引,从而使迭代的寻址无效。如果您将其编码为:

for(int I=0; I < Items.Count, I++)
{
    removeItem(Items[I]);
}

你最终会得到一个索引越界错误,因为该集合的内部索引会重置。

我不能和ReSharper说话,但我猜它有比MS nunit引擎(或者就此而言,MS运行时引擎)更慷慨的运行时引擎。

我在一个应用程序中做了类似的事情,我尝试遍历父项上的依赖对象集合并删除它们。它因您收到的确切错误而失败:最终我使用linq查询删除附加到指定父级的所有项 - 相当于运行SQL查询DELETE FROM table WHERE parentID = parentid