2017-09-14 3 views
0

J'ai donc deux projets de démarrage Spring. Dans le projet A, j'appelle le contrôleur du projet B via une classe de service pour récupérer une ResponseEntity contenant une liste de chaînes. La classe de service du projet A étant le consommateur et B étant le fournisseur dans la terminologie du Pacte:Pacte: non HttpMessageConverter trouvé pour le type de réponse

BookServiceInterfaceImpl.java

@Service("bookService") 
public class BookServiceInterfaceImpl implements BookServiceInterface { 

public ResponseEntity<List<String>> getBookTitlesForCourse(final String courseId){ 
    RestTemplate restTemplate = new RestTemplate(); 
    ResponseEntity<String[]> response = restTemplate.getForEntity("http://localhost:8888/api/book/course/" + courseId, String[].class); 
    List<String> titles = Arrays.asList(response.getBody()); 
    return new ResponseEntity<List<String>>(titles, HttpStatus.OK); 
} 
} 

BookController.java

@RestController 
@RequestMapping("/api") 
public class BookController { 

private BookService bookService; 

@Autowired 
public BookController(BookService bookService) { 
    this.bookService = bookService; 
} 

@RequestMapping(method = RequestMethod.GET, value="/book/course/{id}") 
public ResponseEntity<String[]>getBookTitlesForCourse(@PathVariable("id") final long id) { 
    List<Book> books = bookService.findAllBooks(); 
    if(books.isEmpty()) { 
     return new ResponseEntity<>(HttpStatus.NO_CONTENT); 
    } 
    String[] bookTitles = books.stream() 
      .filter(book -> book.getCourseId() == id) 
      .map(book -> book.getTitle()) 
      .toArray(String[]::new); 
    return new ResponseEntity<String[]>(bookTitles, HttpStatus.OK); 
} 
} 

Je suis en train d'utiliser Pacte pour créer un contrat entre les deux. Jusqu'à maintenant, je le test suivant chez le consommateur:

BookServiceTest.java

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class BookServiceTest { 

@Rule 
public PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("test_provider", "localhost", 8080, this); 

@Pact(provider="test_provider", consumer="test_consumer") 
public RequestResponsePact createPact(PactDslWithProvider builder) { 
    return builder 
      .given("test state") 
      .uponReceiving("BookServiceTest test interaction") 
       .path("/api/book/course/1") 
       .method("GET") 
      .willRespondWith() 
       .status(200) 
       .body("{[\"Dont make me think\",\"Clean Code\"]}") 
      .toPact(); 
} 

@Test 
@PactVerification("test_provider") 
public void test_retrieveBooksForcourse_validCourseId_success() { 
    //given 
    final String courseId = "1"; 
    BookServiceInterfaceImpl bookService = new BookServiceInterfaceImpl(); 
    //when 
    ResponseEntity<List<String>> response = bookService.getBookTitlesForCourse(courseId); 
    //then: 
    assertThat(response.getStatusCode(), is(200)); 
    assertThat(response.getBody().size(), is(2)); 
} 
} 

Et le fichier pom pour le consommateur est:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
<modelVersion>4.0.0</modelVersion> 

<groupId>com.ocr</groupId> 
<artifactId>new-consumer</artifactId> 
<version>0.0.1-SNAPSHOT</version> 
<packaging>jar</packaging> 

<name>new-consumer</name> 
<description>Demo project for Spring Boot</description> 

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.5.6.RELEASE</version> 
    <relativePath /> 
</parent> 

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
    <java.version>1.8</java.version> 
</properties> 

<dependencies> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-actuator</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>au.com.dius</groupId> 
     <artifactId>pact-jvm-consumer-junit_2.11</artifactId> 
     <version>3.5.5</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-devtools</artifactId> 
     <scope>runtime</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-test</artifactId> 
     <scope>test</scope> 
    </dependency> 
</dependencies> 

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-maven-plugin</artifactId> 
     </plugin> 
    </plugins> 
</build> 

Quand je lance, je reçois le texte suivant:

java.lang.AssertionError: Pact Test function failed with an exception: Could not extract response: no suitable HttpMessageConverter found for response type [class [Ljava.lang.String;] and content type [application/octet-stream] 
at au.com.dius.pact.consumer.BaseProviderRule.validateResult(BaseProviderRule.java:164) 
at au.com.dius.pact.consumer.BaseProviderRule$1.evaluate(BaseProviderRule.java:77) 
at org.junit.rules.RunRules.evaluate(RunRules.java:20) 
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class [Ljava.lang.String;] and content type [application/octet-stream] 
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:110) 
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:917) 
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:901) 
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655) 
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613) 
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:312) 
at com.ocr.newconsumer.service.BookServiceInterfaceImpl.getBookTitlesForCourse(BookServiceInterfaceImpl.java:29) 
at com.ocr.newconsumer.controller.BookServiceTest.test_retrieveBooksForcourse_validCourseId_success(BookServiceTest.java:60) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 
at au.com.dius.pact.consumer.BaseProviderRule.lambda$runPactTest$1(BaseProviderRule.java:150) 
at au.com.dius.pact.consumer.BaseMockServer.runAndWritePact(MockHttpServer.kt:152) 
at au.com.dius.pact.consumer.ConsumerPactRunnerKt.runConsumerTest(ConsumerPactRunner.kt:13) 
at au.com.dius.pact.consumer.BaseProviderRule.runPactTest(BaseProviderRule.java:148) 
at au.com.dius.pact.consumer.BaseProviderRule.access$100(BaseProviderRule.java:21) 
at au.com.dius.pact.consumer.BaseProviderRule$1.evaluate(BaseProviderRule.java:76) 
... 20 more 
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 
at au.com.dius.pact.consumer.BaseProviderRule.lambda$runPactTest$1(BaseProviderRule.java:150) 
at au.com.dius.pact.consumer.BaseMockServer.runAndWritePact(MockHttpServer.kt:152) 
at au.com.dius.pact.consumer.ConsumerPactRunnerKt.runConsumerTest(ConsumerPactRunner.kt:13) 
at au.com.dius.pact.consumer.BaseProviderRule.runPactTest(BaseProviderRule.java:148) 
at au.com.dius.pact.consumer.BaseProviderRule.access$100(BaseProviderRule.java:21) 
at au.com.dius.pact.consumer.BaseProviderRule$1.evaluate(BaseProviderRule.java:76) 
... 20 more 

Je ne suis pas exactement ce que la question est, de ce que je sais que je suis sûr que ce genre de conversion ne doit pas être une grande chose et devrait être manipulé par Spring. Y a-t-il quelque chose que je fais de façon incorrecte en ce qui concerne l'appel REST ou le test (la première fois en utilisant Pact)? Ai-je manqué une dépendance dans le pom que j'ai supposé que les parent/dépendances de Spring Start auraient?

Répondre

0

Pour nos tests consommateurs, nous étendons ConsumerPactTestMk2. L'une des méthodes que vous devez remplacer est runTest(MockServer ms). Le MockServer dans la méthode runTest a la partie hôte de l'URL que vous devez utiliser. Vous devez donc modifier l'URL dans la classe imple pour utiliser l'URL augmentée.

public class BookServiceInterfaceImpl implements BookServiceInterface { 
    private String hostUrl = "http://localhost:8888"; 
    //provider setter for this variable. 

Avec cela en place, vous pouvez alors utiliser la hostUrl pour créer votre URL finale.

ResponseEntity<String[]> response = restTemplate.getForEntity(hostUrl + "/api/book/course/" + courseId, String[].class); 

Puis dans la méthode runTest.

@Override 
protected void runTest(MockServer ms) throws IOException { 
    BookServiceInterfaceImpl bookService = new BookServiceInterfaceImpl(); 
    bookService.setHostUrl(ms.getUrl()); 

EDIT: Here is an exmaple.

+0

donc je pense que vous dites que je devrais modifier mon code d'implémentation pour l'adapter à une bibliothèque de test, alors que la bibliothèque de test ne devrait pas faire le travail ici, malgré tout, je vais essayer cette approche quoi que ce soit autour de surcharger runTest dans l'exemple sur github im en utilisant comme référence: https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer-junit/src/test/java/au/com/ dius/pact/consumer/examples/ArticlesTest.java – jbailie1991

+0

Ok, j'ai implémenté le changement et modifié le test pour ressembler à l'exemple affiché. Je reçois toujours la même erreur HttpMessageConverter alors ne pense pas que c'est le problème – jbailie1991

+0

Ah bon point. J'ai déjà vu cette erreur et j'ai toujours trouvé un moyen de contourner le problème. Avez-vous vu cette? https://stackoverflow.com/a/21857557/1490322 –