【问题标题】:Foq Mock.Expect with Times > 1 always failsFoq Mock.Expect with Times > 1 总是失败
【发布时间】:2014-01-28 22:44:34
【问题描述】:

我发现的Mock.Expect 示例中没有一个使用Times 而不是0 或1(从不,一次)。 我修改了 Foq.Usage.fsx 中的一个现有测试,以尝试不是 0 或 1 的东西,但我无法让它工作。

有人看出什么不对了吗?

let [<Test>] ``expect method is called the specified number of times`` () =
    // Arrange
    let xs = Mock.Of<System.Collections.Generic.IList<int>>()
    // Assert (setup)
    Mock.Expect(<@ xs.Contains(0) @>, never)
    Mock.Expect(<@ xs.Contains(1) @>, once)
    Mock.Expect(<@ xs.Contains(2) @>, exactly 2)
    // Act
    xs.Contains(1) |> ignore
    xs.Contains(2) |> ignore
    xs.Contains(2) |> ignore
    // Assert
    verifyAll xs

【问题讨论】:

  • 不要在新代码中这样做(期望在测试开始和断言部分中的verifyAll)! stackoverflow.com/questions/980554/…
  • 我也不喜欢 expect/verifyAll 样式,但如果它在 Foq 中,它应该可以工作 - 除非我误解了它的工作原理。
  • 如果您将Expects 移至Assert 阶段,一切都很好。 (例外是从 Act 阶段产生的(如果期望不是once/atleastonce,第一个触发会导致它爆炸)
  • 我同意应该可以使它可行;我个人的经验是,Foq Just Works(而且你也从 Phillip Trelford 那里得到了极大的响应!)。我会在示例和/或源代码中进行搜索。但问题仍然存在:- 你在做什么,必须以这种方式表达 - 我还没有遇到过这种方法有用的案例
  • 如果您将Expects 移至// Assert 阶段,一切都很好。 (例外来自// Act 阶段(如果期望不是once/atleastonce,第一次触发会导致它爆炸)

标签: unit-testing f# foq


【解决方案1】:

这是Foq 中的一个错误,当您使用Mock.Expect 时,它会检查在模拟调用时是否满足期望。如果未满足给定的期望,则会引发异常。这在理论上可能很有用,因为它在未满足期望的确切点给出了堆栈跟踪。

exactly 2 的问题是期望在一次调用后首先检查,而不是恰好两次。实际上,在调用时,我们希望将 exactly 2 解释为最多两个,而在 verifyAll 处解释为正好两个。

使用Mock.Expectatmost 2 和/或效果后的普通旧验证,您可以更接近我认为您想要的行为:

let [<Test>] ``expect method is called the specified number of times`` () =
    // Arrange
    let xs = Mock.Of<System.Collections.Generic.IList<int>>()
    // Assert (setup)
    Mock.Expect(<@ xs.Contains(0) @>, never)
    Mock.Expect(<@ xs.Contains(1) @>, once)
    Mock.Expect(<@ xs.Contains(2) @>, atmost 2)
    // Act
    xs.Contains(1) |> ignore
    xs.Contains(2) |> ignore
    xs.Contains(2) |> ignore
    // Assert
    Mock.Verify(<@ xs.Contains(2) @>, exactly 2)
    verifyAll xs

感谢您报告问题。该问题现已在源代码中修复,并将在下一个版本中提供。

【讨论】:

  • +1 是 .Verify 排队等待 verifyAll 验证还是 verifyAll 现在是多余的?
  • @RubenBartelink 是的,verifyAll 用于验证使用expectexpectSeq 设置的期望
  • Doh,错过了那一点(我没有看到.Expects)。 Mock.Verify 在这种情况下非常清楚。大声思考[手头没有 FSI](我想知道如果将 Verify 切换到 Expect 会发生什么(即 Expect 是否可以/应该能够替换匹配的前一个,如果可以,让代码这样说会不会更好)
【解决方案2】:

正如 cmets 中所讨论的,这并不能回答您的问题,但是......我会写这个(可行):

let xs = Mock.Of<System.Collections.Generic.IList<_>>()
// Act
xs.Contains(1) |> ignore
xs.Contains(2) |> ignore
xs.Contains(2) |> ignore
// Assert
verify <@ xs.Contains(0) @> never
verify <@ xs.Contains(1) @> once
verify <@ xs.Contains(2) @> <| exactly 2

【讨论】:

    【解决方案3】:

    谢谢你,鲁本。我同意,明确的verifys 是最好的,但是(也根据您的建议)下面的代码可以在任何人想要使用Expect/verifyAll的情况下工作。

    let [<Test>] ``expect method is called the specified number of times`` () =
        // Arrange
        let xs = Mock.Of<System.Collections.Generic.IList<int>>()
        // Act
        xs.Contains(1) |> ignore
        xs.Contains(2) |> ignore
        xs.Contains(2) |> ignore
        // Assert
        Mock.Expect(<@ xs.Contains(0) @>, never)
        Mock.Expect(<@ xs.Contains(1) @>, once)
        Mock.Expect(<@ xs.Contains(2) @>, exactly 2)
        verifyAll xs
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多