Guice ServletScopes.scopeRequest и @RequestParameters при тестировании

Мне приходится иметь дело с некоторым устаревшим кодом. Есть одна точка, где мне нужна такая функция, как

NewCodeAccessor.get(), который дает мне объект, полученный из Guice.

public class NewCodeAccessor {
    @Inject
    public static Provider<PageDataHandle> pageDataHandleProvider;

    public static PageDataHandle get() {
        return pageDataHandleProvider.get();
    }
}

Guice инициализируется ранее и запрашивается статическая инъекция для этого класса.

В рабочем коде это работает нормально, но сейчас я пытаюсь это проверить. PageDataHandle - область запроса, поэтому мой тест выглядит так:

@Before
public void setUp() {
    Injector createInjector = Guice.createInjector(new ServletModule(), 
        new AppModule());
}

@Test
public void testGetInjector() throws Exception {

    // put it inside a callable to wrap it in a request scope, as it would
    // usually be done in a request on the server
    Callable<PageDataHandle> scopeRequest = ServletScopes.scopeRequest(
            new Callable<PageDataHandle>() {
                @Override
                public PageDataHandle call() throws Exception {
                    PageDataHandle data = NewCodeAccessor.get();
                    return data;
                }
            }, Collections.<Key<?>, Object> emptyMap());
    PageDataHandle data = scopeRequest.call();
    assertTrue(data != null);
}

Это все еще работает, пока PageDataHandle или его зависимости не запрашивают инъекцию для параметров запроса:

@Inject @RequestParameters Map<String, String[]> requestParameters

Здесь я получаю исключение OutOfScope: com.google.inject.ProvisionException: ошибки предоставления Guice:

1) Ошибка в пользовательском поставщике, com.google.inject.OutOfScopeException: невозможно получить доступ к объекту scoped >. Либо мы в данный момент не находимся в запросе HTTP-сервлета, либо вы, возможно, забыли> применить com.google.inject.servlet.GuiceFilter в качестве фильтра сервлета для этого запроса.

Я попытался добавить свой собственный тестовый модуль с чем-то вроде этого:

bind(new TypeLiteral<Map<String, String[]>>() {
    }).annotatedWith(com.google.inject.servlet.RequestParameters.class)
    .toInstance(parameters);

Но это не работает, потому что RequestParameters уже связан с ServletRequest.

Что я мог сделать, это следующее: я оставляю ServletModule в инжекторе, который я создаю для своего теста, и привязываю RequestScope к моей собственной, настраиваемой области. Тогда RequestParameters не будет привязан кем-либо еще, поэтому я мог бы создать свою собственную привязку, чтобы смоделировать это. Но это не кажется хорошим. Может ли кто-нибудь сказать мне, как это сделать правильно? Спасибо!

1 ответ

Я определенно рекомендую избегать ServletModule во время тестов (кроме интеграционных тестов). Альтернатива состоит в том, чтобы сделать ServletScopes.scopeRequest() который создаст для вас поддельный объем запроса.

Другие вопросы по тегам