2016-05-26 41 views
1

最初の支払いが成功し、2回目の支払いが失敗したときに最初の支払いをロールバックする必要があるユニットテストケースを作成しています。ユニットテストコードは次のようになります。MOQを使用して異なる返品で同じメソッドを複数回呼び出す

  1. 最初の支払いが正常に処理されます。
  2. 2番目のお支払いを処理します。外部システムは、同様のトランザクションフォールト例外をスローします。同様のトランザクション障害例外を解析してexceptionidを取得し、例外IDを使用して2番目のトランザクションを再度処理します。
  3. 2番目のトランザクションが実際に処理されると、システムは「支払いが失敗しました」という例外を返します。
  4. システムは、最初の支払いを無効にする必要があります。

私は(1)のユニットテストを書いています。どのようにSOコミュニティは、パート2、3、4の世話をする方法についての指針を持っていますか?

 [TestMethod]  
      public void IfTheSecondPaymentFailsThenTheFirstPaymentShouldBeVoided() 
      { 
//Arrange   
     var iPaymentMock = new Mock<IPaymentMock>(); 
       var paymentSpecificationResponse = new PreregisteredAccountSpec();  
       iPaymentMock.Setup(
         counter => counter.ProcessPayment 
          (
           It.IsAny<Context>(), 
           It.IsAny<PreregisteredAccountSpec>(), 
           It.IsAny<Guid>()) 
          ). 
         Returns(paymentSpecificationResponse); 
//Act 
var twoPaymentProcessor = new TwoPaymentProcessor(iPaymentMock.Object); 
twoPaymentProcessor.Submit(); 

//assert 
    iPaymentMock.Verify((
        counter => counter.ProcessPaymentSpecification 
        (
         It.IsAny<Context>(), 
         It.IsAny<PreregisteredAccountSpec>(), 
         It.IsAny<Guid>() 
        ) 
       ), Times.Once()); 
      } 

答えて

1

あなたはモックにSetupSequenceではなくSetupを使いたいように見えます。 これは、あなたが私はあなたが間違って希望しているものの詳細を持っているかもしれないが、SetupSequenceはあなたが呼び出しの順序がが重要である、モック上に複数のリターンを持つことができます

iPaymentMock.SetupSequence(counter => counter.ProcessPayment 
    (
     It.IsAny<Context>(), 
     It.IsAny<PreregisteredAccountSpec>(), 
     It.IsAny<Guid>()) 
    ) 
    .Returns(paymentSpecificationResponse) 
    .Throws(new Exception()); 

ような何かを行うことができます。

+0

SetUpSequenceでlambdaを使用することはできません。これが機能するかどうかは不明です。 –

0

2、3、4のテストにどのようにアプローチすればよいか分かりませんが、タイトルからの一般的な質問に答えるために、模擬の複数の呼び出しから異なる戻り値を得ることができます。 Returns()句。

は、セットアップは、単にこれは、セットアップおよび各呼び出し時に結晶化さresults[index++]を返す場合

[TestMethod] 
public void DifferentResultsOnEachInvocation() 
{ 
    var results = new[] { 
        new Result(1), 
        new Result(2), 
        new Result(3) 
       }; 

    var index = 0; 

    var mockPayment = new Mock<IPayment>(); 
    mockPayment.Setup(mk => mk.ProcessPayment()).Returns(()=>results[index++]); 

    var res = mockPayment.Object.ProcessPayment(); 
    Assert.AreEqual(1, res.Id); 

    res = mockPayment.Object.ProcessPayment(); 
    Assert.AreEqual(2, res.Id); 

    res = mockPayment.Object.ProcessPayment(); 
    Assert.AreEqual(3, res.Id); 

} 

を次のように我々は

public interface IPayment 
{ 
    Result ProcessPayment(); 
} 

public class Result 
{ 

    public Result(int id) 
    { 
     Id = id; 
    } 

    public int Id { get; } 
} 

次我々はProcessPayment()復帰への呼び出しごとに異なる値を持つことができていると言います配列の最初の要素を返します。それをlambaにすることで、ProcessPayment()が呼ばれるたびに評価されます。

+0

これは主に意見ですが、テストからロジックを削除するので、 'SetupSequence'はこのケースで書き込みと読み取りが容易になりませんか? – LukeW

+1

@ LukeW一度オフにしたテストの場合、 'SetupSequence'は簡単ですが、戻り値の配列が固定されていない場合に' Setup'を使い始めました.-戻り値の配列を共通テストメソッドに渡していました。それに慣れていた。 – AlanT

+0

@ AlanT:MockPaymentsの設定方法を高レベルで理解していると思います。私は、外部支払いWebサービスとのやりとりが行われるクラスに関する詳細を追加しました。 –

関連する問題