Reputation: 37000
I have some test-code that is initializing some members which should be done just once at the beginning. This is why I used the constructor for that:
[TestFixture]
public class MyTestClass
{
private readonly IUnitTestGeometryProvider m_GeometryProvider;
public MyTestClass()
{
// do some heavy init-op
}
private IEnumerable<TestCaseData> TestCases()
{
yield return new TestCaseData(this.m_GeometryProvider.GetPolyline())
.Throws(typeof(ArgumentException));
}
[TestCaseSource("TestCases")]
public double Check_GetReducedArea_For_Invalid_Arguments(IGeometry theGeom)
{
return theGeom.GetReducedArea();
}
}
I know of the convention to use the FixtureSetup
-attribute for initializing tests, e.g. from this question on SO. However I noticed that the method TestCases
is executed before the method marked with that attribute so I run into an NullReferenceException
when evaluating the different testcases as the m_GeometryProvider
is null
at this time.
So I debugged my code and set a breakpoint into the constructor. I noticed, that it is executed twice before any test has even been run. I assumed every testcase having its own instance of the MyTestClass
, but as I have three different testcases and the constructor running twice this doesn't explain it.
As the initialization is heavy I´d like to execute it just once. Is there a way to guarantee this? I´d like to avoid a static
member as it often attracts colleagues to heavily use other static
members just because there already is one. Furthermore I´d consider the test-init to be specific for one instance of my MyTestClass
instead of the class itself - assuming there´s just one however.
I'm using NUnit 2.5.10.
Upvotes: 2
Views: 1706
Reputation: 13681
Basically NUnit reserves the right to construct your fixture object whenever it needs to, as often as it needs to. Therefore, you should avoid doing heavy initialization in your constructor, especially if some initialization is only needed when the tests are being run.
Generally, initialization for executing the tests should be done in the TestFixtureSetUp method, which is run once and only once each time the fixture is executed. This is more complicated, however, when you are generating test cases using a TestCaseSource attribute.
Because TestCases must be executed in order to create your tests in the first place, eons before they are ever run, an instance of the object must be created to do that. Then when the tests are run, another instance is created for the purpose of running them. There's not enough info in your question to figure out why there are two "extra" calls to your constructor, but it's either due to some other aspect of your code or simply a bug in the somewhat old version of NUnit you are using. You would have to step through those constructor calls and examine the stack trace to see what is calling them.
Is your m_GeometryProvider member used anywhere else besides the TestCases method? If not, you can simplify things by making it a temporary field created in that method. You can then eliminate an extra constructor call by making the TestCases method static. You said you didn't like that, but it's what we recommend. In fact, in NUnit 3.0 and later it is required to be static.
If you have other initialization that's needed to run tests besides the creation of the geometry provider, that should go in a TestFixtureSetUp method.
Upvotes: 4