Подтвердить что ты не робот

Как тестовые инъекции?

Я дал 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.

4b9b3361

Ответ 1

Для любого сложного проекта 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, поэтому вам очень редко нужно проверить, что введенные объекты non-null в ваших тестах. На самом деле, когда я комментирую конструкторы с @Inject, я не пытаюсь проверить, являются ли параметры null (на самом деле, мои тесты часто вводят null в конструктор, чтобы тесты были простыми).

Ответ 2

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

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

Ответ 3

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

Ответ 4

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