2017-09-14 2 views
0

So habe ich zwei Spring-Boot-Projekte. In Projekt A rufe ich über eine Serviceklasse den Controller von B an, um eine ResponseEntity mit einer Liste von Strings zu erhalten. Projekt A Service-Klasse ist der Verbraucher und B ist der Anbieter in Pact Terminologie:Pakt: kein HttpMessageConverter für Antworttyp gefunden

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); 
} 
} 

Ich versuche zu verwenden Pakt, um einen Vertrag zwischen den beiden zu erstellen. So weit ich den folgenden Test in den Verbraucher:

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)); 
} 
} 

Und die pom-Datei für den Verbraucher:

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> 

Als ich dies ausführen, bekomme ich die folgende: Was

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 

So bin ich nicht genau das Problem ist, von dem, was ich weiß, ich bin ziemlich sicher, diese Art der Umwandlung sollte keine große Sache und sollte von Spring behandelt werden. Gibt es etwas, was ich in Bezug auf den REST-Aufruf oder den Test falsch mache (zum ersten Mal mit Pact)? Fehle ich eine Abhängigkeit in der Pom, dass ich die Spring Boot Eltern/Abhängigkeiten angenommen hätte?

Antwort

0

Für unsere Verbrauchertests erweitern wir ConsumerPactTestMk2. Eine der Methoden, die Sie überschreiben müssen, ist runTest(MockServer ms). Die MockServer in der runTest Methode hat den Host-Teil der URL, die Sie verwenden müssen. Daher müssen Sie die URL in der Klasse imple ändern, um die erweiterte URL zu verwenden.

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

Mit dem im Ort, dann können Sie die hostUrl verwenden Ihre endgültige URL zu erstellen.

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

Dann in der runTest Methode.

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

EDITIEREN: Here is an exmaple.

+0

Also ich denke du sagst, ich sollte meinen Implementierungscode ändern, um zu einer Testbibliothek zu passen, wann sollte nicht die Testbibliothek die Arbeit hier unabhängig machen? Ich werde diesen Ansatz trotzdem versuchen, nur neugierig wie ich nicht sehen kann alles über ridTest im Beispiel auf github im als Referenz verwenden: 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, ich habe die Änderung implementiert und den Test geändert, um dem veröffentlichten Beispiel zu ähneln. Ich bekomme immer noch den gleichen HttpMessageConverter-Fehler, also glaube nicht, dass das das Problem ist – jbailie1991

+0

Ah guter Punkt. Ich habe diesen Fehler schon einmal gesehen und immer einen Weg gefunden. Hast du das gesehen? https://stackoverflow.com/a/21857557/1490322 –

Verwandte Themen