2017-11-23 5 views
1

私はアプリケーションでSpring Securityをテストするためにいくつかのバネ統合テストを作成しています。私はRequestPostProcessorを使用して、異なる権限を持つテストユーザーを作成します。また、私はそれらをすべてのテストで再利用するためにキャッシュします。以下のコードを参照してください:MockHttpServletRequestBuilderがキャッシュされている場合、MockMvc.performは並列ストリームでConcurrentModificationExceptionをスローします

public final class Users { 
    public static final RequestPostProcessor 
     ANONYMOUS = anonymous(); 

    public static final RequestPostProcessor 
     PERMISSIONS_READ = buildUser(Permissions.PERMISSIONS_READ); 
    public static final RequestPostProcessor 
     PERMISSIONS_WRITE = buildUser(Permissions.PERMISSIONS_WRITE); 
    public static final RequestPostProcessor 
     PERMISSIONS_DELETE = buildUser(Permissions.PERMISSIONS_DELETE); 

    public static final RequestPostProcessor 
     ROLES_READ = buildUser(Permissions.ROLES_READ); 
    public static final RequestPostProcessor 
     ROLES_WRITE = buildUser(Permissions.ROLES_WRITE); 
    public static final RequestPostProcessor 
     ROLES_DELETE = buildUser(Permissions.ROLES_DELETE); 

    public static final RequestPostProcessor 
     USERS_READ = buildUser(Permissions.USERS_READ); 
    public static final RequestPostProcessor 
     USERS_WRITE = buildUser(Permissions.USERS_WRITE); 
    public static final RequestPostProcessor 
     USERS_DELETE = buildUser(Permissions.USERS_DELETE); 


    private Users() {} 

    private static RequestPostProcessor buildUser(Permissions permission) { 
     return buildUser(permission.toString(), permission.toString()); 
    } 

    private static RequestPostProcessor buildUser(String name, String... authorities) { 
     return user(name).authorities(SecurityUtils.authoritiesFromStrings(authorities)); 
    } 
} 

をそして、私はテストでそれらを使用する場合、私はConcurrentModificationExceptionを持っています。

使用法:

.................... 
@Autowired private WebApplicationContext context; 
@Autowired private Filter springSecurityFilterChain; 
MockMvc mvc = MockMvcBuilders 
     .webAppContextSetup(context) 
     .addFilters(springSecurityFilterChain) 
     .build(); 
.................... 
MockHttpServletRequestBuilder req = get("some-url"); 
mvc.perform(req.with(Users.ANONYMOUS)) 
     .andExpect(status().isFound()) 
     .andExpect(header().string("Location", "login-url")); 
Stream.of(Users.PERMISSIONS_WRITE, Users.PERMISSIONS_DELETE, 
     Users.ROLES_WRITE, Users.ROLES_DELETE, 
     Users.USERS_WRITE, Users.USERS_DELETE) 
     .parallel() 
     .forEach(Unchecked.consumer(user -> mvc.perform(req.with(user)) //Exception is here and caused by .with(user) 
       .andExpect(status().isForbidden()))); 
.................... 

例外:私は(MockHttpServletRequestBuilder req)、それをキャッシュし、複数のストリームで使用しているので、

.................... 
Caused by: java.util.ConcurrentModificationException 
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) 
at java.util.ArrayList$Itr.next(ArrayList.java:851) 
at org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder.postProcessRequest(MockHttpServletRequestBuilder.java:754) 
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:145) 
at com.ipan.fin.man.integrational.PermissionsTest.lambda$checkReadSecurity$5(PermissionsTest.java:162)//line with my code 
.................... 

例外がorg.springframework.test.web.servlet.request.MockHttpServletRequestBuilderにスローされます。だから、場合、とき

postProcessorsオーバー
@Override 
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { 
    for (RequestPostProcessor postProcessor : this.postProcessors) { //here 
     request = postProcessor.postProcessRequest(request); 
     if (request == null) { 
      throw new IllegalStateException(
        "Post-processor [" + postProcessor.getClass().getName() + "] returned null"); 
     } 
    } 
    return request; 
} 

1回のストリーム反復処理し、二つ目は、新しいpostProcessor

@Override 
public MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor) { 
    Assert.notNull(postProcessor, "postProcessor is required"); 
    this.postProcessors.add(postProcessor); //here 
    return this; 
} 

postProcessors

ConcurrentModificationExceptionが追加されますがスローされます。

2つの理由によりキャッシュMockHttpServletRequestBuilderに許可されていない上に、私は私のコードで理解したよう:安全な

  • MockHttpServletRequestBuilder.with呼び出しが新しいRequestPostProcessorを追加するスレッドないです

    1. 私は予想通り、古いものに置き換えられません。

    私は正しいですか?

    P. sequentalが正常に動作し、私は常に正しい検査結果(サーバからの応答ステータス)を取得するためMockHttpServletRequestBuilder.withの呼び出しは、古いRequestPostProcessorオブジェクトを置き換えるように見えるのテストストリームと

  • 答えて

    1

    はい、あなたの分析が正しい:MockHttpServletRequestBuilderがするように設計されていませんそのように同時に使用することができます。

    とにかくMockHttpServletRequestを作成する際に実際に顕著なオーバーヘッドはありません。

    私はあなたが必要とするたびに新しいリクエストを作成することをお勧めします。そして、パラレルストリームを使用しても、そのようなテストではまったく購入しません。

    要約すると、テストを過度にエンジニアリングしないでください。 ;-)

    よろしく、

    サム(春TestContextフレームワークの著者)

    +0

    ありがとうございました!私は理解した) –

    関連する問題