2017-04-12 12 views
0

git hubにいくつかのコードをアップロードしました。ここには https://github.com/Shaunus87/SyncTestというプロトタイプコードとユニットテストが含まれています。ユニットテスト同期コードに競合条件がありますか?

私は基本的に、私の同期コードを宣言し、イベントをフックアップ、最終的にイベントを呼び出し、イベントが呼び出されたかどうかを主張するメソッドを呼び出します。

 bool called = false; 

     var testBinsToVend = GetRoboBins(); 
     var vendHelper = new VendingHelper(null, testBinsToVend, VendType.Issue); 

     vendHelper.Complete += delegate() { 
      called = true; 
     }; 

     vendHelper.DoVending(); 

     Assert.IsTrue(called); 

すべてのコードが同期している(よう私が知っている限り)、まだ私はテストを実行すると、それを介してデバッグすると失敗します...

私はいくつかのことを試してみました。私は競合条件を持っているか、またはb)イベントの半分を実行しないことを決定したコードを実行しているとき?

何ですか?

編集: 私も以下のような手動リセットイベントを設定しようとしました:

 bool called = false; 
     var done = new ManualResetEvent(false); 

     var testBinsToVend = GetRoboBins(); 
     var vendHelper = new VendingHelper(null, testBinsToVend, VendType.Issue); 

     vendHelper.Complete += delegate() { 
      called = true; 
      done.Set(); 
     }; 

     vendHelper.DoVending(); 

     done.WaitOne(); 
     Assert.IsTrue(called); 
     //was complete called? 
     Assert.AreEqual(true, vendHelper.Bins.All(x => x.State != VendState.Pending)); 

しかしdone.WaitOne();はテストがAssert.IsTrue(called);ラインに到達したことはありませんヒットしたときには、実行の1行だから。

+2

そこには 'System.Threading.Timer'の参照があります。**あなたのコードは同期していますか?そのイベントはどこから発射されたのですか?内部[Timer_Tick](https://github.com/Shaunus87/SyncTest/blob/master/eVendVendingMachines/BaseVendingMachine.cs#L182)?その 'called = true;'行にブレークポイントを置き、コールスタックを調べると、デバッグ中に知っておく必要があることが分かります。 –

答えて

2

ビジネスロジックに問題があります:

private CommCommand GetLastCommand(List<CommCommand> cmds, DateTime since) { 
return cmds.Where(x => x.DateTime > since) 
      .OrderByDescending(x => x.DateTime) 
      .FirstOrDefault(); 
} 

DateTime.Nowは、デフォルトで約20msの程度の解像度を持ちます。つまり、あなたのメッセージはDateTime > sinceが真実になるずっと前に受信されています。コードをステップ実行すると、タイミングが調整されます。Sendは元の受信後にはるかに長く発生します。

メッセージの順序付けにはDateTime.Nowを使用できません。単に正確さが十分ではありません。注文のために送受信の順序に頼ることができると本当に思っている場合(つまり、メッセージが表示される前に返信することはありません)、代わりに簡単なカウンターで置き換えてください。

+0

はい!私はちょうどあなたがそれを注文してからあなたの編集ポップを見たと思うか尋ねていました。ありがとうございました。私はDateTimeがそのようなものについては正確ではないとは考えていませんでした。 DateTimesが実際にどのように問題を発見しましたか?







Smithy

+1

@Smithyまず、Completeハンドラにブレークポイントを設定しました。今は本当に呼び出されませんでした。その後、実際に非同期の問題が発生したため、テストが実行される前にテストが終了していないことを確認しました。ハンドラが呼び出される場所を調べて、あなたが育てることを期待していたものを探しました。次に、事前条件を確認し、メッセージが送信されるたびに出力しました( 'Debug.WriteLine'が便利です)。最後に、FETのWorkOnResponse(最後に正常に動作したコマンド)にブレークポイントを設定し、 'lastRecCmd'がnullであることを確認しました... – Luaan

+1

@Smithy ...' receivedCommands'は空ではなく、応答。これは、 'GetLastCommand'が間違っていることを明らかにしました - そして、私は' DateTime'比較を見たとき、私はそれ以上調べる必要はありませんでした。デバッグは少し芸術です:D – Luaan

関連する問題