Как имитировать контекст безопасности в тестах, если я отключил авторизацию

У меня есть такие тесты:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test")
public class MyTests {

    @Autowired
    private TestRestTemplate restTemplate;
    ....

В тестах я отключил аутентификацию/авторизацию

Но в коде я использую следующее:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

Но это причина, почему тесты терпят неудачу.

Как я могу издеваться над своими тестами?

P.S.

Этот не работает:

@Test
public void testUpdateWithoutNameAndEmail() {
    Authentication authentication = Mockito.mock(Authentication.class);
    SecurityContext securityContext = Mockito.mock(SecurityContext.class);
    Mockito.when(securityContext.getAuthentication()).thenReturn(authentication);
    SecurityContextHolder.setContext(securityContext);
    Mockito.when(authentication.getName()).thenReturn("aName");

    restTemplate.exchange(..

SecurityContextHolder.getContext().getAuthentication() возвращает ноль в коде

и этот тоже:

@Autowired
private TestRestTemplate restTemplate;
@Test
@WithMockUser(username = "aUser", roles = { "ADMIN" })
public void testUpdateWithoutNameAndEmail() {
   ...

person gstackoverflow    schedule 11.09.2017    source источник
comment
вы можете использовать SecurityContextHolder.getContext().setAuthentication() и передать ему какой-нибудь макет Authentication (или реальный экземпляр, если хотите)   -  person    schedule 11.09.2017
comment
@RC. Где мне нужно написать этот код?   -  person gstackoverflow    schedule 11.09.2017
comment
@RC. пожалуйста прочитайте обновление темы   -  person gstackoverflow    schedule 11.09.2017
comment
Вот почему вы должны опубликовать минимальный воспроизводимый пример, если вы используете restTemplate, то вы запрашиваете какой-то реальный сервер. Поэтому вам нужно использовать настоящую аутентификацию (пароль имени пользователя базовую аутентификацию может быть).   -  person    schedule 11.09.2017
comment
@RC, я использую TestRestTemplate и написал это в начальном посте.   -  person gstackoverflow    schedule 11.09.2017
comment
Из javadoc Если вы используете аннотацию @SpringBootTest, TestRestTemplate автоматически доступен и может быть @Autowired добавлен в ваш тест. Если вам нужны настройки (например, для добавления дополнительных конвертеров сообщений), используйте RestTemplateBuilder @Bean. Итак, создайте TestRestTemplare с некоторой аутентификацией (имя пользователя/пароль).   -  person    schedule 11.09.2017
comment
@RC. Но как использовать аннотацию WithMockUser? Какие классы следует использовать?   -  person gstackoverflow    schedule 12.09.2017


Ответы (1)


Вы можете издеваться над Spring Authentication:

Authentication authentication = Mockito.mock(Authentication.class);

И скажите Spring SecurityContextHolder сохранить этот экземпляр Authentication:

SecurityContext securityContext = Mockito.mock(SecurityContext.class);
Mockito.when(securityContext.getAuthentication()).thenReturn(auth);
SecurityContextHolder.setContext(securityContext);

Теперь, если вашему коду требуется Authentication, чтобы что-то вернуть (возможно, имя пользователя), вы просто устанавливаете некоторые ожидания для издевательского экземпляра Authentication обычным способом, например.

Mockito.when(authentication.getName()).thenReturn("aName");

Также есть тестовая аннотация Spring (org.springframework.security.test.context.support.WithMockUser), которая делает это за вас...

@Test
@WithMockUser(username = "aUser", roles = { "anAuthority" })
public void aTest(){
    // any usage of `Authentication` in this test will get an instance withe the user name "aUser" and a granted authority "anAuthority"
    // ...
}
person glytching    schedule 11.09.2017
comment
Я создал объекты по вашему описанию. Я сделал это в начале теста. Но SecurityContextHolder.getContext().getAuthentication() по-прежнему возвращает значение null - person gstackoverflow; 11.09.2017
comment
Я добавил подробности в тему - person gstackoverflow; 11.09.2017
comment
@WithMockUser тоже не работает - person gstackoverflow; 11.09.2017
comment
Возможно, нужно больше подробностей. Вышеупомянутые подходы являются допустимыми способами издевательства над SecurityContext, и я не могу воспроизвести NPE, учитывая информацию в вашем вопросе. - person glytching; 11.09.2017
comment
1. Вы понимаете, что я использую TestRestTemplate для тестирования? SecurityContextHolder.getContext().getAuthentication() возвращает ноль, равный NPE в моем обновлении темы - person gstackoverflow; 11.09.2017