繁体   English   中英

模拟回调顺序边缘案例错误

[英]Mock callback in order edge case bug

我创建了一个扩展方法,用于根据此SO Answer依次调用moq(请参见下文)。

一个示例用例是:

mock.setup.CallbackSequence(new List{h,e,l,l,o})

我在其中向我的SUT传递hello并期望按顺序输入字符。

问题是这种情况:

mock.setup.CallbackSequence(new List{h,e,l,l,o,X})

我在哪里hello 即使由于动态断言的性质而失败(即使X从未发送,但我们永远也不知道),这将通过。 我能想到解决此问题的唯一方法是添加一个

mock.Verify(setupmethod, Times.Exactly(list.Count))

但是,回调设置和验证是在两个不同的地方完成的,因此实现此缺陷将由扩展方法的使用者来决定。 我想避免将它们放在他们身上,因为它注定会失败.....建议?

public static ICallbackResult CallbackSequence<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList) where TMockType : class
{
  //Refactor: Does not fail if it does not reach the end, only if out of order and/or too long
  var index = 0;
  return mockSetup.Callback((T1 t1, T2 t2) =>
  {
    if(index >= sequencedList.Count)
      Assert.That(false, "Sequenced list attempted to access index out of bounds. Count is " + sequencedList.Count + "; index is " + index + "; value being checked is " + t1);
    var currentItemInSequence = sequencedList[index];
    Assert.That(t1, Is.EqualTo(currentItemInSequence), String.Format("Failed sequence at position{0}", index));
    index++;
  });
}

编辑

我唯一想到的可能是返回消费者应该在最后调用的自定义对象:

var sequenceVerifier = ...CallbackSequence();
//Do Stuff
sequenceVerifier.VerifySequence();

这对我来说仍然不是最佳选择,因为这给人的印象是,直到调用VerifySequence才进行验证,但是它只会执行边缘情况。...除非我不在回调中断言,而是跟踪并断言在末尾??????? 可能有用,想法???

与一些同事交谈之后,我们想出了一种双重方法,将其交给实施者。

选项1

返回必须具有其VerifySequenceCalls方法称为的SequenceVerifier

选项2

将我的操作传递到一个辅助方法中,以便它可以设置,操作并验证边缘情况

我可以在第二个选项中使用SequenceVerifier。 然后,由消费者决定他们如何看待代码。

public static MockSequenceVerifier<T1> CallbackInOrderOfSequence<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList) where TMockType : class
{
  var mockSequenceVerifier = new MockSequenceVerifier<T1>(sequencedList);
  mockSetup.Callback((T1 t1, T2 t2) => mockSequenceVerifier.UpdateSequence(t1));
  return mockSequenceVerifier;
}

public static void VerifySequenceAfterActionPerformed<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList, Action actionToPerform) where TMockType : class
{
  var verifier = CallbackInOrderOfSequence<TMockType, T1, T2>(mockSetup, sequencedList);
  actionToPerform();
  verifier.VerifySequence();
}

public class MockSequenceVerifier<T>
{
  private IList<T> SequenceToVerifyAgainst { get; set; } 
  private IList<T> ActualSequence { get; set; } 

  public MockSequenceVerifier(IList<T> sequenceToVerifyAgainst)
  {
    SequenceToVerifyAgainst = sequenceToVerifyAgainst;
    ActualSequence = new List<T>();
  } 

  public void VerifySequence()
  {
    ActualSequence.IsEqualTo(SequenceToVerifyAgainst);
  }

  public void UpdateSequence(T item)
  {
    ActualSequence.Add(item);
  }
}

暂无
暂无

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

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