2014-12-07 19 views
9

Tôi có ứng dụng SpringBoot thông thường với bộ lọc auth tùy chỉnh hoạt động bình thường.Ngoại lệ khi sử dụng TestRestTemplate

Nhưng tôi gặp sự cố khi sử dụng TestRestTemplate trong thử nghiệm tích hợp.

Tôi muốn kiểm tra ở đây nếu người dùng có đăng nhập không thể đăng nhập sai. Nhưng Thay vì ResponseEntity với 401 tình trạng tôi có ngoại lệ:

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: cannot retry due to server authentication, in streaming mode; nested exception is java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode 
    at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:228) 
    at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:220) 
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95) 
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:795) 
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:779) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:559) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:512) 
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:454) 
    at cz.angular.security.basic.rest.AuthorizeControllerTest.userWithWrongCreditials(AuthorizeControllerTest.java:64) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176) 
    at org.junit.runners.Suite.runChild(Suite.java:127) 
    at org.junit.runners.Suite.runChild(Suite.java:26) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) 
Caused by: java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode 
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1280) 
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379) 
    at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:48) 
    at org.springframework.http.client.AbstractClientHttpResponse.getStatusCode(AbstractClientHttpResponse.java:33) 
    at org.springframework.web.client.DefaultResponseErrorHandler.getHttpStatusCode(DefaultResponseErrorHandler.java:56) 
    at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:50) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:552) 
    ... 42 more 

Bên trong mùa xuân ném org.springframework.security.authentication.BadCredentialsException nhưng trong việc sử dụng ứng dụng thực tế của nó dịch sang json trả lời.

Khi sử dụng curl, tôi nhận được phản hồi bình thường.

curl -H "Content-Type: application/json" -d '{"name":"user","password":"password-wrong"}' http://localhost:8080/login 
{"timestamp":"2014-12-07T10:07:27.166+0000","status":401,"error":"Unauthorized","exception":"org.springframework.security.authentication.BadCredentialsException","message":"Bad credentials","path":"/login"} 

mã kiểm tra là ở đây:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
@WebAppConfiguration 
@IntegrationTest("server.port:9999") 
public class AuthorizeControllerTest { 

    public static final String LOCALHOST = "http://localhost:9999"; 

... 

    @Test 
    public void userWithWrongCreditials() throws Exception { 
    RestTemplate rest = new TestRestTemplate(); 

    Credentials credentials = new Credentials(); 
    credentials.setName("user"); 
    credentials.setPassword("password-wrong"); 

    ResponseEntity<Map> response = 
     rest.exchange(
     LOCALHOST + "/login", 
     HttpMethod.POST, 
     new HttpEntity<Credentials>(credentials), 
     Map.class); 

    assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); 
    } 
} 

Toàn dự án có thể được nhìn thấy trong kho lưu trữ

https://bitbucket.org/winsik/security-token-stackoverflow/

Nơi bạn có thể nhìn thấy cả hai bài kiểm tra đi qua và không ai trong AuthorizeControllerTest.

Tôi đã thử rất nhiều thứ như đặt Loại nội dung, v.v. nhưng không có may mắn. Tôi sẽ đánh giá cao bất kỳ ý tưởng nào.

+0

trình cho tôi. Bạn có chắc đó là 'TestRestTemplate' từ Spring Boot không? –

+0

Có TestRestTemplate của nó từ khởi động mùa xuân. Tôi sẽ cố gắng cung cấp mã đầy đủ sớm, có thể có một số vấn đề trong triển khai Bộ lọc nhưng tôi tò mò tại sao Ứng dụng hoạt động như mong đợi (Trả về 401 khi mật khẩu sai được cung cấp) –

+0

@DaveSyer Tôi đã chỉnh sửa câu hỏi và thêm kho lưu trữ với toàn bộ mã . https://bitbucket.org/winsik/security-token-stackoverflow/ Nơi bạn có thể nhìn thấy cả hai kiểm tra vượt qua và lỗi không thành công trong AuthorizeControllerTest. –

Trả lời

17

Bạn cần ứng dụng khách HTTP Apache để có thể tự xử lý lỗi với TestRestTemplate. Điều này làm việc cho tôi với dự án của bạn

<dependency> 
     <groupId>org.apache.httpcomponents</groupId> 
     <artifactId>httpclient</artifactId> 
     <scope>test</scope> 
    </dependency> 

(Tôi cũng loại bỏ các junit, Mockito và mùa xuân-test phụ thuộc nhân đôi.)

+0

Có, nó hoạt động. Cảm ơn bạn rất nhiều, bạn đã giúp tôi rất nhiều. Vì vậy, nếu tôi nhận được nó đúng httpclient sẽ diễn ra mặc định httpClient trong TestRestTemplate? –

+1

Ok, bạn đã tiết kiệm thời gian của tôi. Cảm ơn rất nhiều. Nhưng, tại sao cái lừa này lại giải quyết vấn đề ?! –

0

Tôi không nghĩ Jackson sẽ biết cách chuyển đổi JSON thành Object. Hãy thử Map hoặc một cái gì đó?

+0

Trong thử nghiệm đăng nhập thành công, tôi sử dụng đối tượng UserInfo, tất nhiên nó hoạt động. Ở đây trong kiểm tra đăng nhập sai tôi đã thử cũng Map/LinkedHashMap/String, Object là thử cuối cùng của tôi, nhưng kết quả là luôn luôn giống nhau. –

+0

Có lẽ bạn nên cập nhật câu hỏi để gần hơn với một cái gì đó có thể hoạt động (tức là sử dụng 'Bản đồ' cho kiểu phản hồi)? –

Các vấn đề liên quan