2016-11-09 23 views
3

背景

我在彈簧引導(1.4.0.RELEASE),其不應該被連接到數據源,因此,需要已經簡單REST API接受一個對象並用它以相同的方法返回另一個對象(接口類型)。這(種)不尋常的行爲導致我使用RequestMethod.POST既能夠有@RequestBody@ResponseBody彈簧引導 - REST方法返回接口

@RestController 
public class SomeController { 

    @RequestMapping(value = "/path", method = RequestMethod.POST) 
    public ResponseEntity<SomeInterface> someMethod(@RequestBody SomeClass obj) { 
     SomeInterface toReturn = createSomeInterface(...); 
     return new ResponseEntity<>(toReturn, HttpStatus.OK); 
    } 
} 

我也有一個Test方法:

@RunWith(SpringRunner.class) 
@SpringBootTest(classes = SomeApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 
public class SomeControllerTests { 

    @Autowired 
    private TestRestTemplate restTemplate; 

    @Test 
    public void testSomeMethod() { 
     SomeClass toPost = createPostObj(); 
     ResponseEntity<SomeInterface> respons = this.restTemplate.postForEntity("/path", toPost, SomeInterface.class); 
     assertEquals(HttpStatus.OK, respons.getStatusCode()); 
     assertNotEquals(null, respons.getBody()); 
    } 
} 

然而,這拋出:

org.springframework.http.converter.HttpMessageNotReadableException: 
Could not read document: 
Can not construct instance of SomeInterface: 
abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information 

假設都SomeInterfaceSomeClass是財物等API的和不能改變的,這是可能做到?

注意

我已經盡力了SomeInterface包裝成一個類沒有成功:

public class Wrapper { 
    SomeInterface obj; 
    // getter and setter ... 
} 
+0

'SomeInterface toReturn = createSomeInterface(...);'你有SomeInterface的實現?因爲你不能實例化一個java接口。 –

+0

@IssamELATIF存在一個實現'SomeInterfaceImpl',它是外部API yes的一部分。 –

回答

1

你的控制器是正確的,問題出在你的測試。

控制器方法返回一個SomeInterface實例對象,它由您正在使用的外部API中的某個未知類實現。這可能是一個POJO,或者可能包含Jackson註釋,並且它會自動轉換爲JSON/XML而不會出現任何問題。

但是在測試中,您正在使用RestTemplate來調用您的控制器並將結果綁定到新對象。 RestTemplate需要一個類而不是接口,以便能夠創建新實例並使用從JSON/XML格式的控制器接收的數據填充新實例。

如果您沒有訪問或知道實現該接口在您的測試中使用它的類,你可以改變它來檢查包含到響應文本作爲"Spring Boot documentation"解釋或使用JSON assertion library如果你需要更先進的東西。

+0

'SomeInterface'有一個實現'SomeInterfaceImpl',它首先看起來有點像POJO對象(只有getter和setter)。然而,它是來自類和接口的很長一段繼承,我不確定如何驗證對象是否可以轉換爲JSON/XML格式(沒有Jackson註釋)。你能舉出一個具體的例子來說明我怎樣才能做到 - 「改變它來檢查文字......」_? –

0

不能構造SomeInterface的實例:抽象類型要麼 需要映射到具體類型,具有自定義解串器,或 包含其他類型的信息

傑克遜抱怨傳遞SomeInterface.class作爲參數傳遞給restTemplate.postForEntity方法,傑克遜不能實例化一個接口來傳遞實現。

你的測試應該像

@Test 
public void testSomeMethod() { 
    SomeClass toPost = createPostObj(); 
    ResponseEntity<SomeInterface> respons = this.restTemplate.postForEntity("/path", toPost, SomeInterfaceImpl.class); 
    assertEquals(HttpStatus.OK, respons.getStatusCode()); 
    assertNotEquals(null, respons.getBody()); 
} 
+0

不得不改變爲'ResponseEntity respons = this.restTemplate.postForEntity(「/ path」,toPost,SomeInterfaceImpl.class);'否則我有編譯錯誤。仍然不起作用,但新的堆棧跟蹤:'org.springframework.web.client.RestClientException:無法提取響應:沒有找到合適的HttpMessageConverter用於響應類型[class SomeInterfaceImpl]和內容類型[application/json; charset = UTF-8 ]'。 –

+0

你的類路徑中是否有'com.fasterxml.jackson.core:jackson-databind'? –

+0

是的。我在我的pom.xml中包含'spring-starter-web',其中包含'com.fasterxml.jackson.core:jackson-databind:jar:2.8.1:compile'。 –