【问题标题】:Mock Scala classes that take parameters带参数的模拟 Scala 类
【发布时间】:2019-07-30 14:45:41
【问题描述】:

我正在为一个类(A 类)编写单元测试,该类(A 类)将另一个类(B 类)作为其参数,而该类(B 类)又将另一个类(C 类)作为其参数。我需要模拟 B 类来测试 A 类。但是,模拟不接受类参数。

所以,我创建了一个特征(trait BsTrait),我的 B 类扩展了 BsTrait。根据这个答案 - (ScalaMock. Mock a class that takes arguments)。

我想测试的班级 - class A(b: BsTrait){} B 类 - class B(c: C){} C类-class C{} B类的特征 - trait BsTrait{}

我的单元测试 -

    val mockFactory = mockFunction[C, B]
    val mockClient = mock[BsTrait]
    mockFactory.expects(new C).returning(mockClient)``` 


    Error: /path/to/file/Test.scala:63: type mismatch; found : com.example.BsTrait   required: com.example.B
mockFactory.expects(new C).returning(mockClient)

我也尝试为 mockFunction 添加返回类型,但它抛出了同样的错误。

【问题讨论】:

    标签: scala unit-testing mocking


    【解决方案1】:

    我知道这不是一个直接的解决方案,也许它确实是。

    根据我的经验,在 99% 的情况下您都需要使用模拟框架,而只需编写特征的模拟实现(或其他语言的接口)。是的,它会感觉像样板,但是:

    • 事实证明,您通常会编写更少的代码 - 模拟代码一开始很短,但几乎总是开始有各种变通方法以允许各种调用,有时甚至调用您的测试不关心关于,但必须在那里。你最终会参加很多测试,只是为了测试

    • 一旦您在您的框架中模拟了具有某些测试行为的函数/方法,人们通常不会发现何时不再需要它进行测试,而忘记将其删除。没有任何警告我们的死代码已经死了

    • 您控制的代码更容易根据您的需要进行扩展或修改。你自己的问题就是一个很好的例子。如果你的模拟只是一门课,你就不需要问问题了。现在你的 mock 隐藏在各种反射中,可能是字节码操作(我不知道 ScalaMock 是否这样做,但很多框架都这样做),很可能还有其他令人讨厌的事情,无法调试。

    • 著名的模拟通常难以维护且难以操作。如果你在你的 trait 中添加一个方法,你可能最终需要更新很多测试,即使它不应该影响它们。仅仅因为那些测试以某种隐藏的方式使用它们

    • 在测试你是如何实现你的函数/方法而不是它做什么时,你不会陷入模拟框架的陷阱。 (例如,如果您休息客户端专门调用名为get 的方法,或者它执行get-request 是否重要,无论它调用exchangeget 还是其他什么?)

    所以即使感觉有点矫枉过正,还是要认真考虑这样做。从长远来看,您很可能会编写更少的代码。您编写的代码更加清晰易读,如果不再使用某个函数或方法,您可以将其从您的 trait 中删除,并在您的 mock 上获得编译器警告。你的问题会自动得到解决,因为你只需扩展你的模拟行为就足以让它继续下去。而且你更有可能真正写出好的测试。

    最后,如果你遵循这个建议,只有一件事:让你的模拟保持独立。不要让 B 在你的模拟中使用参数 C。让您的 B 使用列表、地图或任何您需要的东西。重点是测试 A,而不是 B 和 C :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 2013-05-06
      • 2015-10-21
      • 1970-01-01
      • 2011-02-05
      • 2017-10-19
      • 1970-01-01
      • 2011-08-04
      相关资源
      最近更新 更多