2016-04-11 80 views
3

我有使用泽西2依赖注入单元测试

ResourceConfig config = new ResourceConfig() 
       .packages("controller", "exception") 
       .register(new MyDIBinder()); 

哪里MyDIBinder是这样

@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; 
    } 
... 

我注入AccountDao和的AccountService控制器包含的所有绑定(例如

AccountDaoImpl accountDaoImpl = new AccountDaoImpl(); 
bind(accountDaoImpl).to(AccountDao.class); 

现在我想为这个控制器编写一个单元测试,是否有可能将整个AccountController实例及其所有传递依赖注入到测试中?

喜欢的东西

@Inject 
    AccountController accountController; 

回答

3

您可以使用主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); 
    } 
} 

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(); 
     } 
    } 
} 

然后在您的具体类

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()); 
    } 
} 

如果你花了一些时间,我相信你能想出一个更好的抽象测试类的设计。这是我首先想到的。

注意:对于任何请求范围,您可能需要嘲笑它。当运行单元测试时,没有请求上下文,所以测试将失败。

另请参见:

+0

谢谢你的回答!什么是TestBinder? – andreybavt

+0

这是我用来测试我的例子的活页夹。它只包含一个简单的服务绑定。对你而言,这将是MyDIBinding –

+0

@peeskillet请使用TestBinder示例完成此响应。 – 4F2E4A2E