【问题标题】:JustMock - check value of passed method argumentJustMock - 检查传递的方法参数的值
【发布时间】:2015-09-30 21:24:52
【问题描述】:

我使用 JustMock 框架并有以下断言:

Mock.Assert(() => activityListenerMock.PeriodPassed(
  Arg.Matches<Period>(e => e.Length == expectedLength)));

失败并显示神秘消息:

Occurrence expectation failed. Expected at least 1 call. Calls so far: 0

我怎样才能得到更好的消息。我想知道它被称为什么值。

方法实际上被调用但参数错误,因为当我将断言更改为跟随它时:

Mock.Assert(() => activityListenerMock.PeriodPassed(
  Arg.IsAny<Period>()));

【问题讨论】:

  • 你能展示一个简短但完整的例子吗?这样可以更轻松地为您提供帮助。
  • 该消息可能比您想象的更有帮助。这意味着该断言正在使用隐式OccursAtLeast(1)。如果断言的方法没有按照匹配器的预期执行,您的测试将失败。如果您正在调试并且看到正在执行的方法,那是因为正在执行原始方法,而不是模拟的方法。正如您自己发现的那样,当您修复匹配器以实际匹配测试场景时,它会起作用。

标签: c# unit-testing mocking justmock


【解决方案1】:

查看传递给 PeriodPassed 的参数的一种方法是使用 JustMock 的 DebugView

DebugView.IsTraceEnabled = true; 放在测试的开头,并将DebugView.CurrentState 添加到手表。接近尾声时,你会看到一些类似的东西: Invocations: (ByRef ...).PeriodPassed("period value will go here") called 1 time; (signature: ...)

周期值将显示在调用列表中。

另一种方法是将匹配器提取到单独的 lambda 中并使用断点: Predicate<Period> matcher = e => e.Length == expectedLength; Mock.Assert(() => activityListenerMock.PeriodPassed( Arg.Matches<Period>(e => matcher(e))));

现在您可以在谓词中放置一个断点并检查e 参数的值。这是可行的,因为现在谓词不是表达式而是实际函数,所以现在您可以调试它了。

【讨论】:

  • 设置 DebugView.IsTraceEnabled = true 将导致失败消息包含 DebugView.CurrentState 的值。请注意,它会大大减慢您的测试速度。
【解决方案2】:

正如 Stefan Dragnev 所写的。我使用了他的想法,然后添加了逻辑来验证输入。如果不是称为 Assert.Fail() 的预期值。不确定是否有更好的方法,但这有效:

Mock.Arrange(() => _uowMock.Class.Add(
    Arg.Matches<ModelClass>(x => (CheckArgs(x, updated)))))
    .DoNothing().Occurs(3);

....

protected static bool CheckArgs(ModelClass x, int y)
{
    if (x.val != y)
    {
        Assert.Fail("Houston we have a problem");
    }

    return true;
}

【讨论】:

    【解决方案3】:

    之前添加额外的安排也对我有用,但它很hacky:

    Mock.Arrange(() => activityListenerMock.PeriodPassed(Arg.IsAny<Period>())).
      DoInstead((Period p) => Console.WriteLine("Actual " + p.Length+" expected "+expectedLength));
    

    【讨论】:

      【解决方案4】:

      今天遇到了同样的困境,并开始扩展 Krzysztof 的想法,并进行了一些扩展。它很粗糙但很实用。

      public static class JustMockExtensions {
              public static FuncExpectation<T> PrintParams<T, T1>(this FuncExpectation<T> mock) {
                  return mock.DoInstead<T1, T>((arg1, arg2) => {
                      string message = string.Empty;
                      message += Process(arg1);
                      message += Process(arg2);
                      Console.WriteLine(message);
                  });
              }
      
              private static string Process<T>(T obj) {
                  if (typeof(T).IsEnum) {
                      return Enum.GetName(typeof(T), obj);
                  }
                  return obj.ToString();
              }
          }
      

      到目前为止,以这种方式使用它允许它在正常流程中通过管道传输。

      Mock.Arrange(() => foo.bar(Arg.IsAny<Widget>(), Arg.IsAny<WidgetTypeEnum>()))
                      .PrintParams<Widget, WidgetTypeEnum>()
                      .MustBeCalled();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-24
        • 1970-01-01
        • 2016-12-04
        • 1970-01-01
        • 2016-07-31
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多