2008年12月6日土曜日

GuiceのinjectMembers

GuiceにinjectMembers()というメソッドがある事に今更気づいた。例えば、次のような構成があった場合。

  • サービスを提供するインターフェース
    public interface IService {
      int service(int a, int b);
    }
  • サービスの実装
    public class ServiceImpl implements IService {
      public int service(int a, int b) {
        return a + b;
      }
    }
  • サービスを利用するクライアント
    import com.google.inject.Inject;
    
    public class Client {
      @Inject IService service;
      
      public int executeService(int a, int b) {
        return service.service(a, b);
      }
    }
で、次のようなTestを書いたとする。
import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

public class ClientTest {

  private Injector injector;

  @Before
  public void setUp() {
    injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(IService.class).to(ServiceImpl.class);
      }
    });
  }

  @Test
  public void test01() {
    setUp();
    Client client = injector.getInstance(Client.class);
    assertEquals(3, client.executeService(1, 2));
  }

  @Test(expected = NullPointerException.class)
  public void test02() {
    Client client = new Client();
    assertEquals(3, client.executeService(1, 2));
  }
}
test01は当然問題無く実行できるし、test02はinjectorを通さずにnewするからinjectが行われずにぬるぽする。こんなカンジで、自前でnewしたらinjectできなくて当然!とか思ってたけど、injectMembers()というメソッドがある事を知った。これを使えば、自前でnewしても(もしくは自分で制御できないタイミングで外部でnewされてしまう)injectできるの?と試してみた。
  @Test
  public void test03() {
    Client client = new Client();
    injector.injectMembers(client);
    assertEquals(3, client.executeService(1, 2));
  }
あっさり想定通りの動作をしてくれた。便利やなー。
ちなみに、S2ContainerにもinjectDependency()ってのがあるようだ。

コメントを投稿