使用MOQ以不同的回报多次调用相同的方法

时间:2016-05-26 05:22:02

标签: c# .net unit-testing moq

我正在编写一个单元测试用例,当第一笔付款成功并且第二笔付款失败时,我需要回滚第一笔付款。单元测试代码如下所示:

  1. 成功处理第一笔付款。
  2. 处理第二笔付款。外部系统会抛出类似的事务错误异常。使用异常id解析类似的事务错误异常以获取exceptionid并再次处理第二个事务。
  3. 当实际处理第二个交易时,系统返回“付款拒绝故障异常”。
  4. 系统应该取消第一笔付款。
  5. 我已经为(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());  
                }
    

2 个答案:

答案 0 :(得分:2)

看起来你想在模拟上使用SetupSequence而不是Setup。 这允许你做类似

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

我可能有你想要的错误的细节但SetupSequence允许你在模拟上有多个回报,但是调用顺序很重要。

答案 1 :(得分:0)

我不太确定如何处理2,3和4的测试,但是在回答标题中的一般问题时,可以通过在lamba中使用lamba从模拟的多次调用中获得不同的返回值。 Returns()条款。

说我们有以下

public interface IPayment
{
    Result ProcessPayment();
}

public class Result
{

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

    public int Id { get; }
}

我们可以每次调用ProcessPayment()返回不同的值,如下所示

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

}

如果设置只返回results[index++],则在设置时结晶,每次调用都返回数组的第一个元素。通过使它成为lamba,每次调用ProcessPayment()时都会对其进行评估。