and*_*avt 3 java unit-testing dependency-injection jersey jersey-2.0
我有这样的控制器
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class AccountController implements CRUDController<Long, Account> {
private AccountDao accountDao;
private AccountService accountService;
@Inject
public AccountController(AccountDao accountDao, AccountService accountService) {
this.accountDao = accountDao;
this.accountService = accountService;
}
...
Run Code Online (Sandbox Code Playgroud)
我正在使用注入AccountDao和AccountService
ResourceConfig config = new ResourceConfig()
.packages("controller", "exception")
.register(new MyDIBinder());
Run Code Online (Sandbox Code Playgroud)
MyDIBinder包含所有绑定的地方(例如
AccountDaoImpl accountDaoImpl = new AccountDaoImpl();
bind(accountDaoImpl).to(AccountDao.class);
Run Code Online (Sandbox Code Playgroud)
)
现在我想为这个控制器编写一个单元测试,是否可以将整个AccountController实例及其所有传递依赖项注入测试?
就像是
@Inject
AccountController accountController;
Run Code Online (Sandbox Code Playgroud)
您可以使用主IoC容器,只需显式注入测试类.Jersey使用HK2作为其DI框架,其IoC容器是ServiceLocator,它有一个方法inject(anyObject)可以注入任何具有其注册表中的依赖项的对象.
例如,你可以做类似的事情
public class InjectionTest {
@Inject
private TestController controller;
@Before
public void setUp() {
final Binder b = new AbstractBinder() {
@Override
public void configure() {
bindAsContract(TestController.class);
}
};
final ServiceLocator locator = ServiceLocatorUtilities.bind(new TestBinder(), b);
locator.inject(this);
}
@Test
public void doTest() {
assertNotNull(controller);
String response = controller.get();
assertEquals("Hello Tests", response);
}
}
Run Code Online (Sandbox Code Playgroud)
该ServiceLocatorUtilities班是一个辅助类,使我们能够轻松地创建ServiceLocator,然后我们只需要调用inject(this)注入InjectionTest.
如果对所有控制器测试执行此操作似乎重复,则可能需要创建一个抽象基础测试类.也许是这样的
public abstract class AbstractControllerTest {
protected ServiceLocator locator;
private final Class<?> controllerClass;
protected AbstractControllerTest(Class<?> controllerClass) {
this.controllerClass = controllerClass;
}
@Before
public void setUp() {
final AbstractBinder binder = new AbstractBinder() {
@Override
public void configure() {
bindAsContract(controllerClass);
}
};
locator = ServiceLocatorUtilities.bind(new TestBinder(), binder);
locator.inject(this);
}
@After
public void tearDown() {
if (locator != null) {
locator.shutdown();
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的具体课堂上
public class TestControllerTest extends AbstractControllerTest {
public TestControllerTest() {
super(TestController.class);
}
@Inject
private TestController controller;
@Test
public void doTest() {
assertNotNull(controller);
assertEquals("Hello Tests", controller.get());
}
}
Run Code Online (Sandbox Code Playgroud)
如果你花了一些时间,我相信你可以想出一个更好的抽象测试类设计.这是我想到的第一件事.
注意:对于任何请求作用域,您可能只需要模拟它.运行单元测试时,没有请求上下文,因此测试将失败.
也可以看看: