使用 Guice 进行功能测试时出现 InstantiationException
InstantiationException when doing functional testing with Guice
我正尝试在 Play framework 2.4.6
中对我的控制器进行 Guice
测试。
以下代码工作正常:
public class GeneralTest {
@Inject
Application application;
private final AccountService accountServiceMock = mock(AccountService.class);
@Before
public void setup() {
Module testModule = new AbstractModule() {
@Override
public void configure() {
bind(AccountService.class).toInstance(accountServiceMock);
}
};
GuiceApplicationBuilder builder = new GuiceApplicationLoader()
.builder(new ApplicationLoader.Context(Environment.simple()))
.overrides(testModule);
Guice.createInjector(builder.applicationModule()).injectMembers(this);
Helpers.start(application);
}
@After
public void teardown() {
Helpers.stop(application);
}
@Test
public void testLogin() throws SQLException {
RequestBuilder request = new RequestBuilder()
.uri(routes.LoginController.login().url());
running(application, () -> {
assertEquals(OK, route(request).status());
});
}
@Test
public void testCreateAccount() throws SQLException {
RequestBuilder request = new RequestBuilder()
.uri(routes.CreateController.createAccount().url());
running(application, () -> {
assertEquals(OK, route(request).status());
});
}
}
但是,当我尝试组织我的方法时,将 testLogin()
和 testCreateAccount
分成 2 个测试 类,其中包含完全相同的 @Before
和 @After
,我得到 InstantiationException
,似乎在第一个之后执行的任何 类 上,发生在 RequestBuilder
:
行
java.lang.InstantiationException: controllers.CreateController, took 2.656 sec
[error] at java.lang.Class.newInstance(Unknown Source)
[error] at play.api.inject.NewInstanceInjector$.instanceOf(Injector.scala:49)
[error] at router.Routes$$anonfun$routes$$anonfun$applyOrElse$$anonfun$apply.apply(Routes.scala:534)
[error] at router.Routes$$anonfun$routes$$anonfun$applyOrElse$$anonfun$apply.apply(Routes.scala:534)
[error] at play.core.routing.HandlerInvokerFactory$$anon.resultCall(HandlerInvoker.scala:136)
[error] at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$$anon$$anon.invocation(HandlerInvoker.scala:127)
[error] at play.core.j.JavaAction$$anon.call(JavaAction.scala:70)
[error] at play.http.DefaultHttpRequestHandler.call(DefaultHttpRequestHandler.java:20)
[error] at play.core.j.JavaAction$$anonfun.apply(JavaAction.scala:94)
[error] at play.core.j.JavaAction$$anonfun.apply(JavaAction.scala:94)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1(Future.scala:24)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
[error] at play.core.j.HttpExecutionContext$$anon.run(HttpExecutionContext.scala:40)
[error] at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
[error] at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:32)
[error] at scala.concurrent.impl.Future$.apply(Future.scala:31)
[error] at scala.concurrent.Future$.apply(Future.scala:492)
[error] at play.core.j.JavaAction.apply(JavaAction.scala:94)
[error] at play.api.mvc.Action$$anonfun$apply$$anonfun$apply.apply(Action.scala:108)
[error] at play.api.mvc.Action$$anonfun$apply$$anonfun$apply.apply(Action.scala:108)
[error] at scala.Option.getOrElse(Option.scala:121)
[error] at play.api.mvc.Action$$anonfun$apply.apply(Action.scala:107)
[error] at play.api.mvc.Action$$anonfun$apply.apply(Action.scala:96)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$mapM.apply(Iteratee.scala:524)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$mapM.apply(Iteratee.scala:524)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM.apply(Iteratee.scala:560)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM.apply(Iteratee.scala:560)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$$anonfun$apply.apply(Iteratee.scala:536)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$$anonfun$apply.apply(Iteratee.scala:536)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1(Future.scala:24)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
[error] at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(Unknown Source)
[error] at java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
[error] at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Unknown Source)
[error] at java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
[error] at java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
[error] Caused by: java.lang.NoSuchMethodException: controllers.CreateController.<init>()
[error] at java.lang.Class.getConstructor0(Unknown Source)
[error] ... 36 more
我正在关注此处的文档,其中没有显示多个 类:
的设置
https://www.playframework.com/documentation/2.4.x/JavaTestingWithGuice https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection
已更新
原因很简单,Play 正在并行执行测试。为确保它们连续执行,将 parallelExecution in Global := false
放入 build.sbt
。
如果不想使用全局作用域,可以更改作用域轴:
http://www.scala-sbt.org/0.13/docs/Scopes.html#Scoping+by+configuration+axis
完全不需要以下代码:
running(application, () -> {
}
我正尝试在 Play framework 2.4.6
中对我的控制器进行 Guice
测试。
以下代码工作正常:
public class GeneralTest {
@Inject
Application application;
private final AccountService accountServiceMock = mock(AccountService.class);
@Before
public void setup() {
Module testModule = new AbstractModule() {
@Override
public void configure() {
bind(AccountService.class).toInstance(accountServiceMock);
}
};
GuiceApplicationBuilder builder = new GuiceApplicationLoader()
.builder(new ApplicationLoader.Context(Environment.simple()))
.overrides(testModule);
Guice.createInjector(builder.applicationModule()).injectMembers(this);
Helpers.start(application);
}
@After
public void teardown() {
Helpers.stop(application);
}
@Test
public void testLogin() throws SQLException {
RequestBuilder request = new RequestBuilder()
.uri(routes.LoginController.login().url());
running(application, () -> {
assertEquals(OK, route(request).status());
});
}
@Test
public void testCreateAccount() throws SQLException {
RequestBuilder request = new RequestBuilder()
.uri(routes.CreateController.createAccount().url());
running(application, () -> {
assertEquals(OK, route(request).status());
});
}
}
但是,当我尝试组织我的方法时,将 testLogin()
和 testCreateAccount
分成 2 个测试 类,其中包含完全相同的 @Before
和 @After
,我得到 InstantiationException
,似乎在第一个之后执行的任何 类 上,发生在 RequestBuilder
:
java.lang.InstantiationException: controllers.CreateController, took 2.656 sec
[error] at java.lang.Class.newInstance(Unknown Source)
[error] at play.api.inject.NewInstanceInjector$.instanceOf(Injector.scala:49)
[error] at router.Routes$$anonfun$routes$$anonfun$applyOrElse$$anonfun$apply.apply(Routes.scala:534)
[error] at router.Routes$$anonfun$routes$$anonfun$applyOrElse$$anonfun$apply.apply(Routes.scala:534)
[error] at play.core.routing.HandlerInvokerFactory$$anon.resultCall(HandlerInvoker.scala:136)
[error] at play.core.routing.HandlerInvokerFactory$JavaActionInvokerFactory$$anon$$anon$$anon.invocation(HandlerInvoker.scala:127)
[error] at play.core.j.JavaAction$$anon.call(JavaAction.scala:70)
[error] at play.http.DefaultHttpRequestHandler.call(DefaultHttpRequestHandler.java:20)
[error] at play.core.j.JavaAction$$anonfun.apply(JavaAction.scala:94)
[error] at play.core.j.JavaAction$$anonfun.apply(JavaAction.scala:94)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1(Future.scala:24)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
[error] at play.core.j.HttpExecutionContext$$anon.run(HttpExecutionContext.scala:40)
[error] at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
[error] at play.core.j.HttpExecutionContext.execute(HttpExecutionContext.scala:32)
[error] at scala.concurrent.impl.Future$.apply(Future.scala:31)
[error] at scala.concurrent.Future$.apply(Future.scala:492)
[error] at play.core.j.JavaAction.apply(JavaAction.scala:94)
[error] at play.api.mvc.Action$$anonfun$apply$$anonfun$apply.apply(Action.scala:108)
[error] at play.api.mvc.Action$$anonfun$apply$$anonfun$apply.apply(Action.scala:108)
[error] at scala.Option.getOrElse(Option.scala:121)
[error] at play.api.mvc.Action$$anonfun$apply.apply(Action.scala:107)
[error] at play.api.mvc.Action$$anonfun$apply.apply(Action.scala:96)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$mapM.apply(Iteratee.scala:524)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$mapM.apply(Iteratee.scala:524)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM.apply(Iteratee.scala:560)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM.apply(Iteratee.scala:560)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$$anonfun$apply.apply(Iteratee.scala:536)
[error] at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$$anonfun$apply.apply(Iteratee.scala:536)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1(Future.scala:24)
[error] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
[error] at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(Unknown Source)
[error] at java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
[error] at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(Unknown Source)
[error] at java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
[error] at java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
[error] Caused by: java.lang.NoSuchMethodException: controllers.CreateController.<init>()
[error] at java.lang.Class.getConstructor0(Unknown Source)
[error] ... 36 more
我正在关注此处的文档,其中没有显示多个 类:
的设置
https://www.playframework.com/documentation/2.4.x/JavaTestingWithGuice https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection
已更新
原因很简单,Play 正在并行执行测试。为确保它们连续执行,将 parallelExecution in Global := false
放入 build.sbt
。
如果不想使用全局作用域,可以更改作用域轴:
http://www.scala-sbt.org/0.13/docs/Scopes.html#Scoping+by+configuration+axis
完全不需要以下代码:
running(application, () -> {
}