简体   繁体   English

使用最小起订量多次调用相同的方法并获得不同的收益

[英]Calling same method multiple times with different returns using MOQ

I am writing a unit test case where I need to rollback the first payment when the first payment is a success and the second payment fails. 我正在编写一个单元测试用例,当第一次付款成功而第二次付款失败时,我需要回退第一笔付款。 The unit test code looks like the following: 单元测试代码如下所示:

  1. Process first payment successfully. 成功处理首次付款。
  2. Process second payment. 处理第二笔付款。 External system will throw similar transaction fault exception. 外部系统将引发类似的事务故障异常。 Parse similar transaction fault exception to get exceptionid and process second transaction again, using the exception id. 解析类似的事务故障异常以获取exceptionid并使用异常ID再次处理第二个事务。
  3. When the second transaction is actually processed, the system returns a "Payment declined fault exception". 当第二笔交易被实际处理时,系统将返回“付款被拒绝故障异常”。
  4. The system should then void the first payment. 然后,系统应取消第一笔付款。

I have written the unit test for (1). 我已经为(1)编写了单元测试。 How SO community have pointers on how to take care of part 2, 3, 4? 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());  
            }

It looks like you want to use SetupSequence rather than Setup on the mock. 看起来您想使用SetupSequence而不是模拟Setup This allows you to do something like 这使您可以做类似的事情

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

I might have the specifics of what you're wanting wrong but SetupSequence allows you to have multiple returns on a mock, order of calls is important though. 我可能有您想要的错误的详细信息,但SetupSequence允许您在模拟中获得多个返回,但是调用顺序很重要。

I'm not too sure how one might approach the tests for 2, 3, and 4 but in answer to the general question from the title, one can get different returns from multiple invocations of a mock by using a lamba in the Returns() clause. 我不太确定如何进行2、3和4的测试,但是为了回答标题中的一般问题,可以通过在Returns()使用lamba从多次调用模拟中获得不同的收益。条款。

Say we have the following 说我们有以下

public interface IPayment
{
    Result ProcessPayment();
}

public class Result
{

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

    public int Id { get; }
}

We can have each call to ProcessPayment() return a different value as follows 我们可以让每个对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);

}

If the setup simply returns results[index++] this is crystallized upon setup and each invocation returns the first element of the array. 如果安装程序仅返回results[index++]则在安装程序中将其明确化,并且每次调用都将返回数组的第一个元素。 By making it a lamba, it is evaluated each time ProcessPayment() is called. 通过将其设置为lamba,可在每次调用ProcessPayment()时对其进行评估。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM