Как мне проверить инъекции Guice? - PullRequest
28 голосов
/ 15 марта 2010

Я дал Google Guice ответственность за подключение моих объектов. Но как я могу проверить, хорошо ли работают привязки?

Например, предположим, что у нас есть класс A, который имеет зависимость B. Как я могу проверить, что B вводится правильно?

class A {
    private B b;
    public A() {}

    @Inject
    public void setB(B b) {
        this.b = b
    }
}

Обратите внимание, что A не имеет метода getB(), и я хочу сказать, что A.b не null.

Ответы [ 4 ]

41 голосов
/ 18 апреля 2010

Для любого сложного проекта Guice вы должны добавить тесты, чтобы убедиться, что модули могут использоваться для создания ваших классов. В вашем примере, если B был типом, который Guice не мог понять, как создать, то Guice не смог бы создать A. Если A не требовался для запуска сервера, но был необходим, когда ваш сервер обрабатывал запрос, который может вызвать проблемы.

В своих проектах я пишу тесты для нетривиальных модулей. Для каждого модуля я использую requireBinding () , чтобы объявить, какие привязки требует модуль, но не определяет. В своих тестах я создаю инжектор Guice, используя тестируемый модуль и другой модуль, который обеспечивает необходимые привязки. Вот пример использования JUnit4 и JMock:

/** Module that provides LoginService */
public class LoginServiceModule extends AbstractModule {
  @Override 
  protected void configure() {
    requireBinding(UserDao.class);
  }

  @Provides
  LoginService provideLoginService(UserDao dao) {
    ...
  }
}

@RunWith(JMock.class)
public class LoginServiceModuleTest {
  private final Mockery context = new Mockery();

  @Test
  public void testModule() {
    Injector injector = Guice.createInjector(
        new LoginServiceModule(), new ModuleDeps());

    // next line will throw an exception if dependencies missing
    injector.getProvider(LoginService.class);
  }

  private class ModuleDeps extends AbstractModule {
    private final UserDao fakeUserDao;

    public ModuleDeps() {
      fakeUserDao = context.mock(UserDao.class);
    }

    @Override 
    protected void configure() {}

    @Provides
    Server provideUserDao() {
      return fakeUserDao;
    }
  }
}

Обратите внимание, что тест запрашивает только поставщика. Этого достаточно, чтобы определить, что Guice может разрешить привязки. Если LoginService был создан методом провайдера, этот тест не будет проверять код в методе провайдера.

Этот тест также не проверяет, что вы связали правильную вещь с UserDao или что UserDao была правильно определена. Некоторые утверждают, что такие вещи редко стоит проверять; если есть проблема, это случается один раз. Вы должны «испытывать, пока страх не превратится в скуку».

Я считаю, что модульные тесты полезны, потому что я часто добавляю новые точки инъекции, и легко забыть добавить привязку.

Вызов requireBinding() может помочь Guice отловить недостающие привязки, прежде чем он вернет ваш инжектор! В приведенном выше примере тест по-прежнему работал бы, если бы вызовов requireBinding() не было, но мне нравится иметь их, потому что они служат документацией.

Для более сложных модулей (например, моего корневого модуля) я мог бы использовать Modules.override () , чтобы переопределить привязки, которые мне не нужны во время тестирования (например, если я хочу убедиться, что мой корневой объект, который будет создан, я, вероятно, не хочу, чтобы он создавал объект, который будет подключаться к базе данных). Для простых проектов вы можете протестировать только модуль верхнего уровня.

Обратите внимание, что Guice не будет вводить нулевые значения , если поле не помечено @Nullable, поэтому вам очень редко нужно проверять, что введенные объекты не являются нулевыми в ваших тестах. Фактически, когда я аннотирую конструкторы с помощью @Inject, я не пытаюсь проверить, являются ли параметры null (на самом деле, мои тесты часто вводят null в конструктор, чтобы тесты были простыми).

4 голосов
/ 02 ноября 2010

Еще один способ проверить вашу конфигурацию - это иметь набор тестов, который тестирует ваше приложение из конца в конец. Хотя сквозные тесты формально тестируют варианты использования, они косвенно проверяют, правильно ли настроено ваше приложение (что все зависимости подключены и т. Д. И т. Д.). Модульные тесты, с другой стороны, должны фокусироваться исключительно на домене, а не на контексте, в котором развернут ваш код.

Я также согласен с ответом NamshubWriter. Я не против тестов, которые проверяют конфигурацию, если они сгруппированы в отдельный набор тестов для ваших модульных тестов.

2 голосов
/ 15 марта 2010

ИМХО, вы не должны это проверять. Ребята из Google Guice проводят модульные тесты, чтобы утверждать, что инъекции работают как положено - в конце концов, именно для этого и предназначен Guice. Вы должны писать тесты только для своего собственного кода (A и B).

0 голосов
/ 15 марта 2010

Я не думаю, что вам следует проверять наличие закрытых пользователей. Лучше протестировать публичный интерфейс вашего класса. Если член "b" не будет введен, вы, вероятно, получите NullPointerException, выполняющий ваши тесты, что должно быть большим количеством предупреждения.

...