Какие способы тестирования методов зависят от статических методов? - PullRequest
7 голосов
/ 18 апреля 2011

Мне нужно протестировать некоторые классы, связанные с безопасностью, которые зависят от Spring Security. Этот код использует SecurityContextHolder.getContext(), который является статическим. Как я могу протестировать вызывающий метод без настройки всего контекста безопасности?

Мы используем JUnit 4 с Mockito. В часто задаваемых вопросах Mockito довольно явно указывал, что статические методы не поддерживаются. Есть ли альтернатива? Ответ на вопрос Spring Security был бы неплох, но я ищу решение более общей проблемы.

Ответы [ 4 ]

7 голосов
/ 18 апреля 2011

Взгляните на PowerMock , это позволит вам смоделировать статические методы, конструкторы и делать всевозможные другие сумасшедшие вещи, которые вы обычно не могли бы делать с Java. Он интегрируется с большинством насмешливых библиотек, включая mockito (см. Пример http://code.google.com/p/powermock/wiki/MockitoUsage13).

В целом я обнаружил, что это очень полезная библиотека, которая есть в вашем наборе инструментов тестирования (при кодировании Java). Единственное предостережение в том, что, поскольку эта библиотека воспроизводит ваш байт-код, если у вас есть другие библиотеки, которые выполняют инструментирование / манипулирование байт-кодом, вы можете столкнуться с проблемами, но не узнаете, пока не попробуете.

5 голосов
/ 18 апреля 2011

Можно сослаться на следующую проблему и добавить org.springframework.security.core.context.SecurityContextHolderStrategy экземпляр, функциональность которого доступна с Spring Security 3.0.

2 голосов
/ 18 апреля 2011

Вы можете просто позвонить SecurityContextHolder.setContext() с поддельным SecurityContext в вашем коде настройки. SecurityContextHolder просто кажется тонкой оберткой вокруг ThreadLocal, поэтому она должна нормально работать.

1 голос
/ 18 апреля 2011

Может быть рефакторинг кода, чтобы он принимал какой-то интерфейс вместо getContext()? Вам понадобится команда impl, которая делегирует всю работу контексту.


ОБНОВЛЕНИЕ: Код будет выглядеть как

interface SecurityContext {
    void foo();
}

class SpringSecurityContext implements SecurityContext {
    public void foo() {
        // call spring static method here
    }
} 

class TestSecurityContext implements SecurityContext {

    public void foo() {
        // test case logic here
    }
}

class SecurityContextClient {
    private final SecurityContext context;

    public SecurityContextClient(SecurityContext context) {
        this.context = context;
    }

    void useSecurity() {
        context.foo();
    }
}
...