【问题标题】:mock-maker-inline causes test cases having traits with final methods to failmock-maker-inline 导致具有最终方法特征的测试用例失败
【发布时间】:2022-09-23 04:34:55
【问题描述】:

我们需要使用 mock-maker-inline 来模拟一些第三方库(例如 Azure SDK)的最终类。

我们使用以下版本的 scalatest 和 mockito:

scalaVersion := \"2.12.2\"

val ScalaTestVersion              = \"3.2.5\"
val ScalaCheckVersion             = \"1.14.2\"
val MockitoVersion                = \"3.4.0\"
val DockerItVersion               = \"0.9.9\"
val MockJavaMailVersion           = \"1.9\"
val MockitoScalaVersion           = \"1.1.4\"
val ScalaPlusScalaCheckVersion    = \"3.2.2.0\"
val ScalaPlusMockitoVersion       = \"3.2.10.0\"


lazy val MockitoIssueSample = (project in file(\".\"))
  .settings(
    name := \"MockitoIssueSample\",
    libraryDependencies += \"org.scalatest\" %% \"scalatest\" % ScalaTestVersion % Test,
    libraryDependencies += \"org.scalacheck\"                %% \"scalacheck\"               % ScalaCheckVersion % Test,
    libraryDependencies += \"org.mockito\"                   %  \"mockito-core\"             % MockitoVersion  % Test,
    libraryDependencies += \"org.mockito\"                   %% \"mockito-scala\"            % MockitoScalaVersion  % Test,
    libraryDependencies += \"org.scalatestplus\"             %% \"scalacheck-1-14\"          % ScalaPlusScalaCheckVersion  % Test,
    libraryDependencies += \"org.scalatestplus\"             %% \"mockito-3-4\"              % ScalaPlusMockitoVersion  % Test,
  )

在我们的 Scala 应用程序中启用 mock-maker-inline 后,其他使用具有 final 方法的 trait 的测试用例开始失败,并出现以下错误:

[info] - should should invoke area of the appropriate shape *** FAILED ***
[info]   org.mockito.exceptions.misusing.UnnecessaryStubbingException: Unnecessary stubbings detected.
[info] Clean & maintainable test code requires zero unnecessary code.
[info] Following stubbings are unnecessary (click to navigate to relevant line of code):
[info]   1. -> at cortex.mockito.sample.AreaCalculatorSpec$$anon$1.<init>(AreaCalculatorSpec.scala:27)
[info] Please remove unnecessary stubbings or use \'lenient\' strictness. More info: javadoc for UnnecessaryStubbingException class.
[info]   at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
[info]   at scala.Option.fold(Option.scala:158)
[info]   at cortex.mockito.sample.AreaCalculatorSpec.withFixture(AreaCalculatorSpec.scala:13)
[info]   at org.scalatest.wordspec.AnyWordSpecLike.invokeWithFixture$1(AnyWordSpecLike.scala:1075)
[info]   at org.scalatest.wordspec.AnyWordSpecLike.$anonfun$runTest$1(AnyWordSpecLike.scala:1087)
[info]   at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306)
[info]   at org.scalatest.wordspec.AnyWordSpecLike.runTest(AnyWordSpecLike.scala:1087)
[info]   at org.scalatest.wordspec.AnyWordSpecLike.runTest$(AnyWordSpecLike.scala:1069)
[info]   at org.scalatest.wordspec.AnyWordSpec.runTest(AnyWordSpec.scala:1879)
[info]   at org.scalatest.wordspec.AnyWordSpecLike.$anonfun$runTests$1(AnyWordSpecLike.scala:1146)
[info]   ...

我们已经用测试 Scala 应用程序模拟了这个问题。如果我们禁用 mock-maker-inline 那么这个测试用例可以工作。在这里,在这个示例应用程序中,我们只添加了一个有问题的测试用例。

下面是示例代码:

  1. 形状.scala

    包 mockito.sample

    特征形状{

    最终定义打印区域():单位= { println(s\"区域为:$getArea()\") }

    def getArea(): 双倍

    }

  2. 矩形.scala

    包 mockito.sample

    类矩形(l:长,b:长)扩展形状{

    覆盖 def getArea(): Double = { 磅 }

    }

  3. 面积计算器.scala

    包 mockito.sample

    类面积计算器(形状:形状){

    def printArea(): 布尔 = { 形状.printArea() 真的 }

    }

  4. AreaCalculatorSpec.scala

    包 mockito.sample

    导入 org.mockito.integrations.scalatest.IdiomaticMockitoFixture

    导入 org.scalatest.concurrent.ScalaFutures

    导入 org.scalatest.matchers.must.Matchers.convertToAnyMustWrapper

    导入 org.scalatest.matchers.should.Matchers

    导入 org.scalatest.wordspec.AnyWordSpec

    导入 org.scalatest.{EitherValues, TryValues}

    导入 org.scalatestplus.scalacheck.ScalaCheckPropertyChecks

    类 AreaCalculatorSpec 扩展 AnyWordSpec 与匹配器 使用 ScalaFutures 使用 EitherValues 使用 TryValues 使用 IdiomaticMockitoFixture 使用 ScalaCheckPropertyChecks {

    特征设置{ val 矩形 = 模拟 [矩形] val areaCalculator = new AreaCalculator(矩形) }

    \"AreaCalculator#printArea\" 应该 { \"应该调用适当形状的区域\" 在新设置 { rectangle.getArea() 应该返回 40.0 areaCalculator.printArea() 必须为真 } }

    }

    请检查并建议您的宝贵意见。让我知道是否需要任何其他详细信息。

    谢谢,

    拉克什·丹胡基亚

    标签: scala unit-testing mockito


    【解决方案1】:

    你如何禁用mock-maker-inline

    如果您可以将mockitoscalatest 更新到最新版本,这应该会消失:我尝试重现错误,但在我的情况下测试通过了。

    看来IdiomaticMockitoFixture 已被弃用,您应该使用IdiomaticMockito

    但是,我在添加 mock-maker-inline 时确实收到了这个警告:

    OpenJDK 64-Bit Server VM warning: Sharing is only supported for 
      boot loader classes because bootstrap classpath has been appended
    

    不过,它似乎是无害的。我尝试禁用我的Instrumenting agent,但我仍然明白。 (删除mock-maker-inline 会使警告消失)

    这是代码,稍作修改:

    trait Shape {
      final def printArea(): Unit = println(s"Area is: $getArea")
      def getArea: Double
    }
    
    class Rectangle(l: Long, b: Long) extends Shape {
      override def getArea: Double = l * b
    }
    
    class AreaCalculator(shape: Shape) {
      def printArea(): Boolean = {
        shape.printArea()
        true
      }
    }
    

    AreaCalculatorSpec 更新了新的依赖项:

    import org.mockito.IdiomaticMockito
    import org.scalatest.concurrent.ScalaFutures
    import org.scalatest.matchers.must.Matchers.convertToAnyMustWrapper
    import org.scalatest.matchers.should.Matchers
    import org.scalatest.wordspec.AnyWordSpec
    import org.scalatest.{EitherValues, TryValues}
    import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
    
    class AreaCalculatorSpec
        extends AnyWordSpec
        with Matchers
        with ScalaFutures
        with EitherValues
        with TryValues
        with IdiomaticMockito
        with ScalaCheckPropertyChecks {
    
      trait Setup {
        val rectangle: Rectangle = mock[Rectangle]
        val areaCalculator = new AreaCalculator(rectangle)
      }
    
      "AreaCalculator#printArea" should {
        "should invoke area of the appropriate shape" in new Setup {
          rectangle.getArea shouldReturn 40.0
          areaCalculator.printArea() mustBe true
        }
      }
    }
    

    我的mock-maker-inline 的设置:

    我的build.sbt:

    libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.12" % Test
    libraryDependencies += "org.scalamock" %% "scalamock" % "5.2.0" % Test
    libraryDependencies += "org.scalatestplus" %% "scalacheck-1-16" % "3.2.12.0" % Test
    libraryDependencies += "org.scalatestplus" %% "mockito-4-5" % "3.2.12.0" % Test
    libraryDependencies += "org.mockito" % "mockito-core" % "4.6.1" % Test
    libraryDependencies += "org.mockito" %% "mockito-scala" % "1.17.7" % Test
    

    【讨论】:

    • 感谢@Alin 的回复。 <br/> 在在这里提出之前,我已经更新到scalatest.org/plus/mockito/versions 中找到的最新兼容版本。 <br/> 更新到最新版本导致其他测试用例失败,因此保留为上述列表中提到的最新版本。<br/> 但是,在按照您的建议更新版本并替换 IdiomaticMockitoFixture 后,此示例代码中的失败测试用例得到解决。对于最新版本,如果我们使用 IdiomaticMockitoFixture,那么这个测试用例仍然会失败。<br/> 将检查实际应用程序并进一步更新。谢谢。
    • 谢谢,它也适用于实际应用。由于版本更新需要解决许多编译错误,但最终成功了。再一次感谢你 !!!
    猜你喜欢
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    相关资源
    最近更新 更多