Статьи

Перемешивание SecurityContext в тестах на Джерси

Джерси имеет прекрасную возможность написать интеграционный тест для REST-API, написанный на Джерси. Просто продлите класс JerseyTest и сделайте это.

Я столкнулся с проблемой, когда мне пришлось смоделировать SecurityContext , чтобы SecurityContext включал специальный UserPrincipal . Сложность заключается в том, что в тестах Джерси упаковывает SecurityContext в собственный класс SecurityContextInjectee . Поэтому я должен добавить свой макет SecurityContext к классу-оболочке этого Джерси. Позвольте мне продемонстрировать это на примере.

Допустим, у меня есть следующий ресурс Джерси:

01
02
03
04
05
06
07
08
09
10
@Path("hello/world")
public class MyJerseyResource {
 
  @GET
  public Response helloWorld(@Context final SecurityContext context) {
    String name = context.getUserPrincipal().getName();
    return Response.ok("Hello " + name, MediaType.TEXT_PLAIN).build();
  }
 
}

В моем тесте я должен смоделировать SecurityContext , чтобы во время тестов мог использоваться предопределенный пользовательский принципал. Я использую Mockito в качестве основы для насмешек. Мой макет выглядит следующим образом

1
2
3
4
5
6
7
final SecurityContext securityContextMock = mock(SecurityContext.class);
       when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
          @Override
          public String getName() {
              return "Alice";
          }
      });

Для добавления этого поддельного SecurityContext в класс-оболочку SecurityContextInjectee мне нужно настроить ResourceConfig с измененным ContainerRequestContext в моем тесте на Джерси. В этом модифицированном ContainerRequestContext можно установить макет SecurityContext, а затем он будет использован в классе оболочки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@Override
   public Application configure() {
       final SecurityContext securityContextMock = mock(SecurityContext.class);
       when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
          @Override
          public String getName() {
              return "Alice";
          }
      });
 
      ResourceConfig config = new ResourceConfig();
      config.register(new ContainerRequestFilter(){
          @Override
          public void filter(final ContainerRequestContext containerRequestContext) throws IOException {
              containerRequestContext.setSecurityContext(securityContextMock);
          }
      });
      return config;
   }

Затем весь тест для моего ресурса выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MyJerseyResourceTest extends JerseyTest {
 
    @Test
    public void helloWorld() throws Exception {
        Response response = target("hello/world").request().get();
 
        assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
        assertThat(response.getEntity()),isEqualTo("Hello Alice");
    }
 
   @Override
   public Application configure() {
       final SecurityContext securityContextMock = mock(SecurityContext.class);
       when(securityContextMock.getUserPrincipal()).thenReturn(new Principal() {
          @Override
          public String getName() {
              return "Alice";
          }
      });
 
      ResourceConfig config = new ResourceConfig();
      config.register(new ContainerRequestFilter(){
          @Override
          public void filter(final ContainerRequestContext containerRequestContext) throws IOException {
              containerRequestContext.setSecurityContext(securityContextMock);
          }
      });
      return config;
   }

У вас есть более разумное решение этой проблемы? Дайте мне знать и напишите комментарий ниже.

Опубликовано на Java Code Geeks с разрешения Сандры Парсик, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Mocking SecurityContext в тестах на Джерси

Мнения, высказанные участниками Java Code Geeks, являются их собственными.