我正在使用Scala中的Mockito和Specs 2编写单元测试。我有一个类Foo
,其方法bar
在其输入参数x
的域中部分定义。如果没有为给定的输入值定义结果,则抛出FooException
:
public abstract class Foo {
public abstract int bar(String x) throws FooException;
}
public class FooException extends Exception {}
现在我正在尝试使用Mockito创建一个模拟器。我希望指定该栏仅返回x
和y
的结果,否则会抛出异常:
import org.specs2.mutable.Specification
import org.specs2.mock.Mockito
import org.mockito.Matchers._
class FooTest extends Specification with Mockito {
val foo = mock[Foo]
foo.bar("x") returns 1
foo.bar("y") returns 2
foo.bar(anyString) throws mock[FooException]
"Foo.bar()" should {
"return an integer for x" in {
foo.bar("x") must be equalTo(1)
}
"throw an exception for z" in {
foo.bar("z") must throwA[FooException]
}
}
}
不幸的是,这个测试失败了。如何以我的测试通过的方式编写模拟?
更新
测试失败,因为在运行时抛出异常。上面的代码导致:
java.lang.NullPointerException
[error] Could not run test FooTest: java.lang.NullPointerException
如果按照其中一个答案中的建议更改顺序,我会得到以下堆栈跟踪:
[error] Could not create an instance of FooTest
[error] caused by java.lang.Exception: Could not instantiate class FooTest: null
[error] org.specs2.reflect.Classes$class.tryToCreateObjectEither(Classes.scala:93)
[error] org.specs2.reflect.Classes$.tryToCreateObjectEither(Classes.scala:207)
[error] org.specs2.specification.SpecificationStructure$$anonfun$createSpecificationEither$2.apply(BaseSpecification.scala:119)
[error] org.specs2.specification.SpecificationStructure$$anonfun$createSpecificationEither$2.apply(BaseSpecification.scala:119)
[error] scala.Option.getOrElse(Option.scala:120)
[error] org.specs2.specification.SpecificationStructure$.createSpecificationEither(BaseSpecification.scala:119)
[error] org.specs2.runner.SbtRunner.org$specs2$runner$SbtRunner$$specificationRun(SbtRunner.scala:73)
[error] org.specs2.runner.SbtRunner$$anonfun$newTask$1$$anon$5.execute(SbtRunner.scala:59)
[error] sbt.TestRunner.runTest$1(TestFramework.scala:84)
[error] sbt.TestRunner.run(TestFramework.scala:94)
[error] sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:219)
[error] sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:219)
[error] sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:207)
[error] sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:219)
[error] sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:219)
[error] sbt.TestFunction.apply(TestFramework.scala:224)
[error] sbt.Tests$$anonfun$7.apply(Tests.scala:196)
[error] sbt.Tests$$anonfun$7.apply(Tests.scala:196)
[error] sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45)
[error] sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45)
[error] sbt.std.Transform$$anon$4.work(System.scala:64)
[error] sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
[error] sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
[error] sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
[error] sbt.Execute.work(Execute.scala:244)
[error] sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
[error] sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
[error] sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:262)
[error] java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:262)
[error] java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
[error] java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
[error] java.lang.Thread.run(Thread.java:744)
[error] caused by java.lang.NullPointerException
答案 0 :(得分:0)
您需要更改存根的顺序。首先对通用行为进行存根(anyString),然后再添加更具体的行为。所以这样做:
val foo = mock[Foo]
foo.bar(anyString) throws mock[FooException]
foo.bar("x") returns 1
foo.bar("y") returns 2
答案 1 :(得分:-1)
您可以在模拟上设置回调:
val foo = mock[Foo]
foo.bar(anyString) answers (derp => {
derp match {
case "x" => 1
case "y" => 2
case _ => throw mock[FooException]
}
})
specs2 documentation中有更多详细信息。