使用 Mockito 监视带有对象参数的方法导致 NullPointerException
Using Mockito to spy a method with object argument results in NullPointerException
我正在尝试使用 Mockito.spy
测试一些代码,以便为我需要提供的某些功能提供行为。虽然我知道我正在做的事情可能有更好的选择,但我很好奇为什么以下代码在 Scala 中抛出 NullPointerException
以及如何解决它。
classFoo
正在测试中。它包含一个方法 act
,为了本题的目的,它只是计算数字的总和。 Class FooSpec
是 class Foo
的相应单元测试。 Class Bar
是另一个 class 用作 class Foo
的参数来证明出现异常的情况。
以下代码 有效 。方法 Foo.act
不接受任何参数。
package foo
import org.mockito.Matchers.any
import org.mockito.Mockito.{spy, times, verify, when}
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class Foo {
def act(): Int = {
(1 to 10).sum
}
}
class FooSpec extends WordSpec with MockitoSugar {
"a test" in {
val spiedFoo = spy(new Foo)
when(spiedFoo.act()).thenReturn(100)
val result = spiedFoo.act()
assert(result == 100)
verify(spiedFoo, times(1)).act()
}
}
以下代码 中断 。方法 Foo.act
接收 1 个 Bar
类型的参数。它出于某种原因抛出 java.lang.NullPointerException
package foo
import org.mockito.Matchers.any
import org.mockito.Mockito.{spy, times, verify, when}
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
case class Bar(value: Int)
class Foo {
def act(bar: Bar): Int = {
(1 to bar.value).sum
}
}
class FooSpec extends WordSpec with MockitoSugar {
"a test" in {
val spiedFoo = spy(new Foo)
when(spiedFoo.act(any[Bar])).thenReturn(100)
val aBar = Bar(10)
val result = spiedFoo.act(aBar)
assert(result == 100)
verify(spiedFoo, times(1)).act(any[Bar])
}
}
测试得到的错误信息如下:
[info] FooSpec:
[info] - a test *** FAILED ***
[info] java.lang.NullPointerException:
[info] at foo.Foo.act(FooSpec.scala:12)
[info] at foo.FooSpec$$anonfun.apply$mcI$sp(FooSpec.scala:19)
[info] at foo.FooSpec$$anonfun.apply(FooSpec.scala:17)
[info] at foo.FooSpec$$anonfun.apply(FooSpec.scala:17)
[info] at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
[info] at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info] at org.scalatest.Transformer.apply(Transformer.scala:22)
[info] at org.scalatest.Transformer.apply(Transformer.scala:20)
[info] at org.scalatest.WordSpecLike$$anon.apply(WordSpecLike.scala:1078)
[info] at org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196)
[info] ...
[info] Run completed in 761 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 0, failed 1, canceled 0, ignored 0, pending 0
[info] *** 1 TEST FAILED ***
[error] Failed tests:
[error] foo.FooSpec
[error] (foo/test:testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 6 s, completed Oct 15, 2019 5:50:20 PM
Important gotcha on spying real objects 州
Sometimes it's impossible or impractical to use when(Object)
for
stubbing spies. Therefore when using spies please consider
doReturn|Answer|Throw()
family of methods for stubbing.
因此尝试
doReturn(100).when(spiedFoo).act(any[Bar])
而不是
when(spiedFoo.act(any[Bar])).thenReturn(100)
也考虑搬到 mockito-scala,例如
class FooSpec extends WordSpec with Matchers with IdiomaticMockito with ArgumentMatchersSugar {
"a test" in {
val spiedFoo = spy(new Foo)
100 willBe returned by spiedFoo.act(*)
val aBar = Bar(10)
val result = spiedFoo.act(aBar)
result shouldEqual 100
spiedFoo.act(*) was called
}
}
我正在尝试使用 Mockito.spy
测试一些代码,以便为我需要提供的某些功能提供行为。虽然我知道我正在做的事情可能有更好的选择,但我很好奇为什么以下代码在 Scala 中抛出 NullPointerException
以及如何解决它。
classFoo
正在测试中。它包含一个方法 act
,为了本题的目的,它只是计算数字的总和。 Class FooSpec
是 class Foo
的相应单元测试。 Class Bar
是另一个 class 用作 class Foo
的参数来证明出现异常的情况。
以下代码 有效 。方法 Foo.act
不接受任何参数。
package foo
import org.mockito.Matchers.any
import org.mockito.Mockito.{spy, times, verify, when}
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class Foo {
def act(): Int = {
(1 to 10).sum
}
}
class FooSpec extends WordSpec with MockitoSugar {
"a test" in {
val spiedFoo = spy(new Foo)
when(spiedFoo.act()).thenReturn(100)
val result = spiedFoo.act()
assert(result == 100)
verify(spiedFoo, times(1)).act()
}
}
以下代码 中断 。方法 Foo.act
接收 1 个 Bar
类型的参数。它出于某种原因抛出 java.lang.NullPointerException
package foo
import org.mockito.Matchers.any
import org.mockito.Mockito.{spy, times, verify, when}
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
case class Bar(value: Int)
class Foo {
def act(bar: Bar): Int = {
(1 to bar.value).sum
}
}
class FooSpec extends WordSpec with MockitoSugar {
"a test" in {
val spiedFoo = spy(new Foo)
when(spiedFoo.act(any[Bar])).thenReturn(100)
val aBar = Bar(10)
val result = spiedFoo.act(aBar)
assert(result == 100)
verify(spiedFoo, times(1)).act(any[Bar])
}
}
测试得到的错误信息如下:
[info] FooSpec:
[info] - a test *** FAILED ***
[info] java.lang.NullPointerException:
[info] at foo.Foo.act(FooSpec.scala:12)
[info] at foo.FooSpec$$anonfun.apply$mcI$sp(FooSpec.scala:19)
[info] at foo.FooSpec$$anonfun.apply(FooSpec.scala:17)
[info] at foo.FooSpec$$anonfun.apply(FooSpec.scala:17)
[info] at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
[info] at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info] at org.scalatest.Transformer.apply(Transformer.scala:22)
[info] at org.scalatest.Transformer.apply(Transformer.scala:20)
[info] at org.scalatest.WordSpecLike$$anon.apply(WordSpecLike.scala:1078)
[info] at org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196)
[info] ...
[info] Run completed in 761 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 0, failed 1, canceled 0, ignored 0, pending 0
[info] *** 1 TEST FAILED ***
[error] Failed tests:
[error] foo.FooSpec
[error] (foo/test:testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 6 s, completed Oct 15, 2019 5:50:20 PM
Important gotcha on spying real objects 州
Sometimes it's impossible or impractical to use
when(Object)
for stubbing spies. Therefore when using spies please considerdoReturn|Answer|Throw()
family of methods for stubbing.
因此尝试
doReturn(100).when(spiedFoo).act(any[Bar])
而不是
when(spiedFoo.act(any[Bar])).thenReturn(100)
也考虑搬到 mockito-scala,例如
class FooSpec extends WordSpec with Matchers with IdiomaticMockito with ArgumentMatchersSugar {
"a test" in {
val spiedFoo = spy(new Foo)
100 willBe returned by spiedFoo.act(*)
val aBar = Bar(10)
val result = spiedFoo.act(aBar)
result shouldEqual 100
spiedFoo.act(*) was called
}
}