アルゴリズムテストを挿入効果テストに置き換える

予想どおり、「 古いプロジェクトでTDDを実装するためのルール 」という記事のメソッドのアルゴリズムをテストしないというルール8は、「どのように」「なぜ」という最も多くの質問を引き起こしました。 最後の記事を書いている時点では、それは明らかなように思えたので、この点について詳しくは説明しませんでした。 しかし、以来 多くの疑問が生じました。私のビジョンを説明したいと思います。 そのため、猫の下には小さなコード例と、テスト方法の2つの例があります。



前の記事を実行することを強制しないために、「メソッドのアルゴリズムをテストしないでください」というルールをもう一度示します。

ここでは、ルールの名前の選択に失敗しましたが、まだ最高の名前が出ていません。 「Mochists」(テストに濡れる人)の中には、特定のメソッドへの呼び出し回数をチェックしたり、呼び出し自体を検証したりする人がいます。つまり、メソッドの内部動作をチェックします。 これはプライベートテストと同じくらい悪いです。 唯一の違いは、このようなチェックの適用レベルです。 このアプローチでも多くの脆弱なテストが行​​われるため、TDDが一部の人によって通常とは認識されないのです。


次のハンドラコードがあります。



public class SomeEventHandler { public SomeEventHandler(IDatabaseCommands dbCommands, IEventValidator validator, IMessagingLogger messagingLogger) { // skipped } public HandlerResult Handle(EventPayload payload) { if (Validator.IsOurEvent(payload)) if (Validator.IsValid(payload)) { var evt = Mapper.Map<Event>(payload); try { using (var tran = new TransactionScope()) { DbCommands.SaveEvt(evt); MessagingLogger.Received(payload); tran.Complete(); } } catch (Exception ex) { return MessageHandlerResult.Fatal; } } else { var error = Validator.GetErrors(); MessagingLogger.InvalidEvent(payload, error); return MessageHandlerResult.Fatal; } return MessageHandlerResult.Success; } }
      
      





Handle()メソッドの動作をテストする必要があります。 問題は、DbCommandsメソッドとMessagingLoggerメソッドが呼び出されたことを確認することです。



モチストアプローチ



彼は、対応するインターフェイスをmokiクラスのコンストラクターに渡し、対応するメソッドが呼び出されたかどうかを確認します:SaveEvt()、Received()、またはInvalidEvent()。 コードは次のようになります。



 public void Should_save_valid_data_and_log_to_messaging_events() { var builder = new EventPayload { // skipped }; var validator = Mock.Of<IEventValidator>(); var dbCommands = new Mock<IDatabaseCommands>(); var messagingLogger = new Mock<IMessagingLogger>(); var handler = new SomeEventHandler(dbCommands, validator, messagingLogger); var result = handler.Handle(payload); // assertions Assert.Equal(MessageHandlerResult.Success, result); dbCommands.Verify(m => m.SaveEvt(It.IsAny<Event>(), Times.Once()) messagingLogger.Verify(m => m.Received(It.IsAny<EventPayload>(), Times.Once()) }
      
      





ネモキストのアプローチ



彼は偽のオブジェクトを作成し、メソッド呼び出しではなく、イベント全体が完了したかどうかを確認します。 この場合、コードは次のようになります。



 public void Should_save_valid_data_and_log_to_messaging_events() { var builder = new EventPayload { // skipped }; var validator = Mock.Of<IEventValidator>(); var dbCommands = new FakeDatabaseCommands(); var messagingLogger = new FakeMessagingLogger(); var handler = new SomeEventHandler(dbCommands, validator, messagingLogger); var result = handler.Handle(payload); // assertions Assert.Equal(MessageHandlerResult.Success, result); Assert.True(dbCommands.IsEventSaved); Assert.True(messagingLogger.IsEventRegistered); }
      
      





そして、偽オブジェクトのメソッドは次のようになります。



 public void SaveEvt(Event evt) { IsEventSaved = true; }
      
      





この場合、IsEventSavedは偽オブジェクトでのみ宣言されます。



長所と短所



最初のアプローチは簡単で迅速ですが、メソッドを変更する必要がある場合、同じ状況で他のメソッドの代わりに一方を呼び出す必要がある場合、テストを修正する必要があります。



2番目の方法では、追加のエンティティが作成され、メソッドの置き換えが必要な状況でのみ利益が得られます。 この場合、偽物やテストの内容を変更する必要さえありません。 もう一つのプラスは、より理想的ですが、非モコイストはテストを行い、テストされたメソッドの内部構造を知らないことです。 したがって、個人的には、時間が許せば、偽物のテストを行います。



All Articles