在 scalatest 中测试方法时,是否可以模拟/存根在方法调用中实例化的对象? [英] When testing a method in scalatest, is it possible to mock/stub an object which is instantiated inside the method call?
问题描述
现在我正在为一个方法编写一个测试套件,该方法接受一个字符串,实例化一个数据库端点,然后用字符串查询端点.然后它接受这个响应,对其执行几次转换,并最终返回它.大致是这样的:
Right now I am writing a testing suite for a method which takes in a string, instantiates a database endpoint, and then queries the endpoint with the string. It then takes this response, performs several transformations to it, and ultimately returns it. It looks roughly like this :
method(s: String){
dbEndpoint database = new dbEndpoint()
DataFrame df = database.read(s)
df.transform(...)
}
由于我已经为数据库端点编写了测试并且确信它足够健壮,所以我只关心确保在数据库查询之后发生的转换逻辑是正确的.因此,我想存根端点,以便 endpoint.read() 返回少量数据,可以轻松验证其转换的正确性.
Since I have already written tests for the database endpoint and am confident that it is sufficiently robust, I am only concerned with ensuring that the transformation logic that occurs after the database query is correct. As a result, I want to stub the endpoint such that endpoint.read() returns a small amount of data whose transformation can easily be verified for correctness.
我的理解是不可能存根这个特定的端点,因为我没有在方法范围之外引用它.我错了吗?有什么方法可以让我从外部对数据库进行存根/模拟(不改变方法)?
It is my understanding that it is not possible to stub this specific endpoint, since I have no reference to it outside of the scope of the method. Am I wrong? Is there some way that I could go about stubbing/mocking the database from the outside (without changing the method)?
推荐答案
警告:使用 PowerMock 确实可以做到这一点,尽管它只能作为@bruno-bonanno 建议的最后手段来完成.
WARNING: This is indeed possible using PowerMock, although it should be done only as last resort as suggested by @bruno-bonanno.
PowerMock 支持模拟硬连线的本地范围依赖项,例如 dbEndpoint
,使用以下三个工具:
PowerMock supports mocking of hardwired local scope dependencies, such as dbEndpoint
, using the following three facilites:
PowerMockito.whenNew
@RunWith
@PrepareForTest
这是一个使用 Scala、PowerMock、Mockito 和 JUnit 的工作示例:
Here is a working example using Scala, PowerMock, Mockito and JUnit:
import org.scalatest.junit.AssertionsForJUnit
import org.junit.Assert._
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.mockito.Mockito._
class Hardwired {
def f(i: Int): String = s"I am a real Hardwired instance"
}
class Foo {
def bar(i: Int): String = {
val localHardwiredInstance = new Hardwired()
localHardwiredInstance.f(i)
}
}
@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[Foo]))
class ExampleSuite extends AssertionsForJUnit {
@Test def mockLocalHardwiredDependency() {
val hardwiredMock = mock(classOf[Hardwired])
when(hardwiredMock.f(3)).thenReturn("I am a mocked Hardwired instance")
PowerMockito.whenNew(classOf[Hardwired]).withNoArguments().thenReturn(hardwiredMock)
val foo = new Foo
assertEquals("I am a mocked Hardwired instance", foo.bar(3))
}
}
build.sbt:
libraryDependencies ++= Seq(
scalaTest % Test,
"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,
),
testOptions += Tests.Argument(TestFrameworks.JUnit, "-v")
我不确定如何使用 ScalaTest 运行它 - 我相信我们需要一个相应的 PowerMockRunner
,但是目前我找不到.
I am unsure how to run it with ScalaTest - I believe we need a corresponding PowerMockRunner
, however currently I was unable to find one.
这篇关于在 scalatest 中测试方法时,是否可以模拟/存根在方法调用中实例化的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!