scala - 在 Scala 中调用静态模拟时出现 NotAMockException
问题描述
我正在尝试在 Scala 中使用 PowerMockito 来绕过对scala.io.Source.fromURL
Source 类中的静态方法的调用。我已经非常接近让这个工作,但我一直得到NotAMockException
.
import com.sun.xml.internal.messaging.saaj.util.ByteInputStream
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import scala.io.BufferedSource
import scala.io.Source
@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[Source]))
class UtilsTest {
@Test def someTest() {
PowerMockito.mockStatic(classOf[Source])
val a = "hello"
Mockito.doReturn(
new BufferedSource(
new ByteInputStream(a.getBytes, 6), 6))
.when(Source).fromURL(anyString)
}
}
我收到以下错误when
:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!
Example of correct stubbing:
doThrow(new RuntimeException()).when(mock).someMethod();
知道我做错了什么吗?我正确地嘲笑了这门课,不是吗?
[编辑]
我的 build.sbt (显然是瘦身):
import _root_.sbtassembly.AssemblyPlugin.autoImport._
name := "yahoo-cml"
organization := "com.yahoo"
version := "0.1.0"
scalaVersion := "2.11.8"
lazy val yahooNexusRepo = "Nexus" at "http://pp-nexus.office.yahoo.com/content/groups/public"
lazy val cpArchiva = "cpArchiva" at "http://cp-archiva.office.yahoo.com"
lazy val yahooRepo = "NexusXP" at
"http://pp-nexus.office.yahoo.com/content/repositories/yahoo-releases"
fullResolvers ++= Seq(
yahooNexusRepo,
cpArchiva,
yahooRepo
)
libraryDependencies ++= Seq(
// scalatest is exlcuded due to conflict with testing libraries.
"org.apache.spark" %% "spark-core" % "2.1.0" % "provided"
exclude("org.scalatest", "scalatest_2.11"),
"org.apache.spark" %% "spark-sql" % "2.1.0" % "provided",
"org.apache.spark" % "spark-hive_2.11" % "2.1.0" % "provided",
"org.apache.spark" % "spark-mllib_2.11" % "2.1.0" % "provided",
// Command line parser
"com.frugalmechanic" %% "scala-optparse" % "1.1.1",
// SBT Junit is supported through junit-interface
"com.novocode" % "junit-interface" % "0.11" % "test",
// scalacheck added explicitely to avoid below error due to higher version of scalacheck.
// "org.scalacheck" % "scalacheck_2.11" % "1.12.5" % "test",
// ScalaTest is test framework for scala
// "org.scalatest" % "scalatest_2.11" % "3.0.1" % "test",
// Added as this is optional dependency for generating HTML reports in scalatest.
"org.pegdown" % "pegdown" % "1.6.0" % "test",
// spark test framework.
"com.holdenkarau" % "spark-testing-base_2.11" % "2.1.0_0.6.0" % "test",
// mockito
"org.powermock" % "powermock-api-mockito" % "1.7.4" % Test,
"org.powermock" % "powermock-core" % "1.7.4" % Test,
"org.powermock" % "powermock-module-junit4" % "1.7.4" % Test,
"org.mockito" % "mockito-core" % "1.10.19" % Test,
"com.novocode" % "junit-interface" % "0.11" % Test,
// fastUtil efficient type specific collection library
"it.unimi.dsi" % "fastutil" % "8.2.1"
)
// Create a default Scala style task to run with compile
(scalastyleConfig in Compile) := baseDirectory.value / "scalastyle-config.xml"
lazy val compileScalastyle = taskKey[Unit]("compileScalastyle")
compileScalastyle := org.scalastyle.sbt.ScalastylePlugin.scalastyle.in(Compile).toTask("").value
(compile in Compile) <<= (compile in Compile) dependsOn compileScalastyle
// Create a default Scala style task to run with tests
lazy val testScalastyle = taskKey[Unit]("testScalastyle")
testScalastyle := org.scalastyle.sbt.ScalastylePlugin.scalastyle.in(Test).toTask("").value
(test in Test) <<= (test in Test) dependsOn testScalastyle
// Configure Java source code style checking plugin.
checkstyleConfigLocation := CheckstyleConfigLocation.File("checkstyle-config.xml")
checkstyleSeverityLevel := Some(CheckstyleSeverityLevel.Error)
(checkstyle in Compile) <<= (checkstyle in Compile) triggeredBy (compile in Compile)
(checkstyle in Test) <<= (checkstyle in Test) triggeredBy (compile in Test)
// Specifying scalatest style traits for uniformity.
// All scala test classes should extend this style ONLY.
testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-y", "org.scalatest.PropSpec")
testOptions in Test += Tests.Argument(TestFrameworks.JUnit, "-v")
testOptions in Test ++= Seq(Tests.Argument(TestFrameworks.ScalaTest, "-o"),
Tests.Argument(TestFrameworks.ScalaTest, "-h", "target/scala-2.11/scalatest-reports"))
testOptions in Test += Tests.Argument("-oD") // test execution time recording.
parallelExecution in Test := false
fork in Test := true
javaOptions ++= Seq("-Xms512M", "-Xmx2048M",
"-XX:MaxPermSize=2048M", "-XX:+CMSClassUnloadingEnabled")
// Coverage settings
// Coverage is disabled by default to avoid Scoverage's runtime dependency in application jar.
// Enable coverage explicitly when needed. like,
// sbt coverage clean test coverageReport
// Do not use coverage when publishing jar
// coverageEnabled := true
coverageMinimum := 70
coverageFailOnMinimum := false
coverageHighlighting := true
// Do not include scala librabries in assembly jar.
assemblyOption in assembly :=
(assemblyOption in assembly).value.copy(includeScala = false)
// assembly name here should match to same generated by publishLocal.
assemblyJarName := "cml_" + scalaBinaryVersion.value + "-assembly.jar"
// addArtifact(artifact in (Compile, assembly), assembly)
// https://books.sonatype.com/nexus-book/reference/sbt.html
// SBT publish settings.
credentials += Credentials("Sonatype Nexus Repository Manager",
"pp-nexus.office.yahoo.com",
"yahooUser", "password")
publishTo <<= version { v: String =>
val nexus = "http://pp-nexus.office.yahoo.com/"
if (v.trim.endsWith("SNAPSHOT")) {
Some("snapshots" at nexus + "content/repositories/yahoo-snapshots/")
} else {
Some("releases" at nexus + "content/repositories/yahoo-releases/")
}
}
解决方案
这里需要注意两点。
作为一般规则,
object
s 会妨碍您的测试能力,因此,如果它们扩展了一个 trait,您应该耦合到它,然后将其object
作为默认实现注入,或者您只需将它们包装在您自己的 trait 中并耦合到它。Mocks 主要用于替换您自己的类/特征,而不是第 3 方的,因此,这里最好的做法是将调用包装到您自己的组件中(并对其进行集成测试),然后耦合到那个,这将允许你轻松地模拟它。
推荐阅读
- progressive-web-apps - PWA - 渐进式 Web 应用程序架构
- android - 在 API 响应中获取 JSONElement
- eyeshot - 如何在视野范围内获得 BlockReference 的 boxmin
- javascript - 我不能使用滑动切换
- php - php输出构造函数数组
- elixir - 如何在 Elixir 中进行模式匹配?
- javascript - 什么是在 jQuery 上显示数据的最佳方式,看起来像带有滚动条的控制台
- postgresql - postgresql 逻辑复制 - 无法删除订阅
- java - 发送到另一个控制器时,类中的 JavaFX ArrayList 为空
- php - 收到 mail() 多个或格式错误的换行错误