Torbjörn Hansson
Torbjörn Hansson

Reputation: 19433

Unit test fails with NUnit Test Adapter but not with ReSharper in VS2012

I have a strange problem occurring when I run my unit tests in VS2012. I'm using NUnit and run them with ReSharper and there all tests are working. But when my colleagues run the tests, some of them don't have ReSharper so they are using the Test Explorer with the extension NUnit Test Adapter (Beta 3) v0.95.2 (http://visualstudiogallery.msdn.microsoft.com/6ab922d0-21c0-4f06-ab5f-4ecd1fe7175d). However with that extension some tests are failing.

The specific code that fails is the following:

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

The exception is:

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)

Now, I'm not looking for an to answer why I get this exception, sure I can understand why it fails. But what I can't understand is why the tests fail with the Test Exporer but not when using ReSharper. Why do I get different behavior for the tests?

I used ildasm.exe to see if the code is compiled differently when testing for the two cases, but the IL-code is identical.

The tests also runs during commit on our Team City server with no errors.

Furthermore, when debugging the test I get the same exception when debugging through NUnit test adapter, but when debugging and stepping through the code with ReSharper, no exception at all.

Upvotes: 3

Views: 798

Answers (1)

Kate Paulk
Kate Paulk

Reputation: 383

I found that in VS2012 similar code would fail at run-time with the same error. If you used this method in an application, would it succeed?

You're functionally iterating over a collection and removing items from it while you're still in the collection - this changes the internal indexing of the collection, invalidating the addressing of the iteration. If you'd coded it as:

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

you'd wind up with an index out of bounds error because the collection's internal indexing resets.

I can't speak to ReSharper, but I'd guess that it has a more generous run-time engine than the MS nunit engine (or, for that matter, the MS runtime engine).

I was doing something similar in an application where I tried to iterate through the collection of dependent objects on my parent and remove them. It failed with the exact error you're receiving: ultimately I went with a linq query to remove all items attached to the specified parent - the equivalent of running the SQL query DELETE FROM table WHERE parentID = parentid.

Upvotes: 1

Related Questions