Playframework 2.6 [Java]:含@Inject的控制器测试方法求助
嘿,我来帮你解决Play Framework里测试带@Inject的控制器这个问题!其实核心就是处理依赖注入的测试场景,分单元测试和集成测试两种方式,我给你详细说下具体实现:
先明确前提
假设你的PersonController是这样的(带注入的依赖,比如PersonService):
import play.mvc.Controller; import play.mvc.Result; import javax.inject.Inject; public class PersonController extends Controller { private final PersonService personService; // 通过@Inject注入依赖 @Inject public PersonController(PersonService personService) { this.personService = personService; } // 要测试的createPerson方法 public Result createPerson(String name, int age) { Person newPerson = new Person(name, age); personService.save(newPerson); return ok("Person created successfully"); } }
方式一:单元测试(隔离依赖)
单元测试的目标是只测控制器本身的逻辑,把依赖用Mock替代,避免依赖真实的数据库或服务。这里用Mockito来Mock依赖,配合Guice来注入Mock实例:
测试代码示例
import org.junit.Test; import static org.mockito.Mockito.*; import play.mvc.Result; import static play.test.Helpers.*; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; public class PersonControllerUnitTest { @Test public void testCreatePerson_ShouldReturnOkAndCallService() { // 1. Mock依赖的PersonService PersonService mockPersonService = mock(PersonService.class); // 2. 创建Guice模块,绑定Mock实例到PersonService接口 Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(PersonService.class).toInstance(mockPersonService); } }); // 3. 从Injector获取控制器实例(自动注入Mock依赖) PersonController controller = injector.getInstance(PersonController.class); // 4. 调用要测试的方法 Result result = controller.createPerson("Alice", 30); // 5. 验证返回结果是否符合预期 assertEquals(OK, result.status()); assertEquals("Person created successfully", contentAsString(result)); // 6. 验证Mock的服务是否被正确调用 verify(mockPersonService).save(any(Person.class)); } }
方式二:集成测试(完整流程)
如果要测试从路由到控制器再到服务的完整流程,就用集成测试。Play提供了GuiceOneAppPerTest基类,帮你启动测试用的Application实例,自动处理依赖注入:
测试代码示例
import org.junit.Test; import play.test.GuiceOneAppPerTest; import play.mvc.Result; import static play.test.Helpers.*; import javax.inject.Inject; public class PersonControllerIntegrationTest extends GuiceOneAppPerTest { // 自动注入真实的控制器实例(Play会帮你处理依赖注入) @Inject private PersonController personController; @Test public void testCreatePerson_DirectCall() { // 直接调用控制器方法测试 Result result = personController.createPerson("Bob", 25); assertEquals(OK, result.status()); assertEquals("Person created successfully", contentAsString(result)); } @Test public void testCreatePerson_ViaRoute() { // 更贴近真实场景:模拟HTTP请求,通过路由访问控制器 Result routeResult = route(app, fakeRequest(POST, "/create-person") .withFormUrlEncodedBody("name", "Charlie", "age", "35") ); assertEquals(OK, routeResult.status()); } }
必要的测试依赖
记得在build.sbt里添加测试相关的依赖,不然会报错:
libraryDependencies ++= Seq( guice, "org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test, "org.mockito" % "mockito-core" % "5.6.0" % Test )
简单总结下:单元测试适合快速验证控制器逻辑,隔离外部依赖;集成测试适合验证完整的请求流程,确保各个组件协同工作正常。根据你的需求选对应的方式就行!
内容的提问来源于stack exchange,提问作者MaVa
相关产品推荐
相关产品推荐

