2017-06-02 9 views
1

いくつかのメンバを初期化するテストコードがありますが、最初は一度だけ行う必要があります。私はそのためにコンストラクタを使用する理由はここにある:Unit-Testを2回実行するコンストラクタ

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

私がテストを初期化するためのFixtureSetup -attributeを使用するには、条約の知っている、例えばthis question on SOから。しかし、私は方法TestCasesがその属性でマークされたメソッドの前に実行されることに気づいたので、m_GeometryProviderが今度はnullであるので、異なるテストケースを評価するときにはNullReferenceExceptionに入ります。

私は自分のコードをデバッグし、コンストラクタにブレークポイントを設定しました。私は、テストが実行される前に2回実行されることに気付きました。私はすべてのテストケースがMyTestClassという独自のインスタンスを持っていると仮定しましたが、3つの異なるテストケースがあり、2回実行されるコンストラクタはそれを説明しません。

初期設定が重いので、一度だけ実行したいと思います。これを保証する方法はありますか?私はstaticのメンバーを避けたいのですが、すでにあるメンバーがいるので他のメンバーを大量に募集してくれることがよくあります。さらに私は、テストのinitが、クラスそのものではなく、私のMyTestClassのインスタンスに固有であると考えています。

私はNUnit 2.5.10を使用しています。

+0

初期化にコンストラクタを使用しないでください。 'TestFixtureSetup'属性はコンストラクタではなく、重い初期化に使用してください。テストごとに、初期化メソッドは 'SetUp'属性でマークされます。 BTW 2.5.10は非常に古いです。現在のバージョンは3.7 –

+0

@ PanagiotisKanavos私はすでにこれが私にとってうまくいかない理由を説明しました。問題は、その属性を使って、マークされたメソッドがfar * after * tha 'TestCases'メソッドで実行され、後者がNREに実行されるということです。 – HimBromBeere

+1

@ PanagiotisKanavos TestCasesがセットアップ前に実行されてからエラーが発生する –

答えて

4

基本的に、NUnitは、必要なときにいつでも、あなたの什器オブジェクトを構築する権利を留保します。したがって、コンストラクタで重い初期化を行わないようにする必要があります。特に、テストの実行中に初期化が必要な場合があります。

一般に、テストを実行するための初期化は、フィクスチャが実行されるたびに1度だけ実行されるTestFixtureSetUpメソッドで実行する必要があります。ただし、TestCaseSource属性を使用してテストケースを生成する場合は、これはより複雑です。

テストケースは実行前に最初にテストを作成するために実行する必要があるため、そのためにオブジェクトのインスタンスを作成する必要があります。テストが実行されると、テストを実行する目的で別のインスタンスが作成されます。あなたの質問にはコンストラクタへの2回の "余分な"呼び出しがあるのを理解するのに十分な情報はありませんが、あなたのコードのいくつかの面や使用している若干古いバージョンのNUnitのバグです。それらのコンストラクタ呼び出しをステップ実行してスタックトレースを調べて、それらを呼び出すものを確認する必要があります。

あなたのm_GeometryProviderメンバはTestCasesメソッドのほかに使用されていますか?そうでない場合は、そのメソッドで作成された一時フィールドにすることで、単純化することができます。 TestCasesメソッドを静的にすることで、余分なコンストラクター呼び出しを排除できます。あなたはそれが好きではないと言ったが、それは我々が推奨するものだ。実際、NUnit 3.0以降では静的である必要があります。

ジオメトリプロバイダの作成以外のテストを実行するために必要な他の初期化がある場合は、TestFixtureSetUpメソッドを使用する必要があります。

+0

現在、geometryProviderはそのメソッドで使用されていますが、より多くのテストが実装されると、それらのメソッドからもアクセスする必要があります。しかし、その答えがありがたいことをたくさんありがとう、私はすでに仮定したいくつかの事柄、特に3.xの方法は静的である必要があるという事実を明らかにしました。 – HimBromBeere

+0

私はそれをデバッグしようとしましたが、両方の呼び出しで、同じスタックトレースに1つのメソッド( 'JetBrains.ReSharper.UnitTestRunner.nUnit26.dll!JetBrains.ReSharper.UnitTestRunner.nUnit26.DelegatingTestRunner.RunTests(...)' )。 'OtherTestCases'という名前の' TestCaseSourceAttribute'でマークされた2番目のメソッドを追加しました。このメソッドは、コンストラクタが** 3 **回呼び出されるようにします。だから明らかに、エンジンは 'TestCaseSource'のたびにコンストラクタを呼び出します。 – HimBromBeere

+0

ああ...以前はResharperについて言及していなかった。うまくいけば、違いはありません。 はい、メソッドに含まれる静的でないTestCaseSourceの__eachを使用するためにコンストラクタが呼び出されます。 NUnitのいくつかのバージョンでは、1つのインスタンスをキャッシュしようとしていますが、それはずっと前のことです。 :-) – Charlie

関連する問題