当前位置: 首页 > 知识库问答 >
问题:

Wiremck为Spring Cloud合同存根运行程序返回错误的内容类型

危钱明
2023-03-14

我第一次试用Spring Cloud合同。我试图让我的客户机自动发现合同存根,但即使我的合同在响应中指定了“application/json”的内容类型,我从WireMock获得的内容类型仍然是“application/octet”。我做错了什么?

我的服务中有一个简单的方法,它从/statusendpoint返回这样的模型:

{
  "name": string,
  "status": string
}

我的合同是这样的:

import org.springframework.cloud.contract.spec.Contract

Contract.make {
    request {
        method('GET')
        headers {
            contentType(applicationJson())
        }
        url("/status")
    }

    response {
        status OK()
        body(
                name: "Demo",
                status: "RUNNING"
        )
        headers {
            contentType(applicationJson())
        }
    }
}

在我的客户端中,我有一个类,它使用SpringRestTemboard来查询此endpoint:

@Component
public class StatusClient {

    private final RestTemplate restTemplate;

    public StatusClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public Status getStatus() {
        return this.restTemplate
                .exchange("http://localhost:8080/status", HttpMethod.GET, null, Status.class)
                .getBody();
    }
}

@Data
class Status implements Serializable {
    private String name;
    private String status;
}

我的单元测试使用@autoconfiguresubrunner从本地存储库中提取合同的最新版本,并根据合同的响应进行断言(例如name=Demo,status=RUNNING)。

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureStubRunner(ids = {"com.example:contract-demo:+:8080"}, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class StatusClientTests {

    @Autowired
    private StatusClient client;

    @Test
    public void testThatStatusReturnsSuccessfully() {
        Status result = this.client.getStatus();
        assertEquals("Demo", result.getName());
        assertEquals("RUNNING", result.getStatus());
    }
}

当我运行测试时,WireMock报告它按预期收到的合同:

2018-05-31 11:36:49.919  INFO 14212 --- [tp1255723887-26] WireMock                                 : Request received:
127.0.0.1 - GET /status

User-Agent: [Java/1.8.0_161]
Connection: [keep-alive]
Host: [localhost:8080]
Accept: [application/json, application/*+json]



Matched response definition:
{
  "status" : 200,
  "body" : "{\"name\":\"Demo\",\"status\":\"RUNNING\"}",
  "headers" : {
    "contentType" : "application/json"
  },
  "transformers" : [ "response-template" ]
}

Response:
HTTP/1.1 200
contentType: [application/json]

但是,当RestTemplate尝试对其进行反序列化时,它会抛出一个异常,因为响应内容类型实际上是“application/octet”,一旦它点击提取数据的方法:

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.contractclientdemo.Status] and content type [application/octet-stream]

    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:119)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:991)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:974)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:725)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:680)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:600)
    at com.example.contractclientdemo.StatusClient.getStatus(StatusClient.java:18)

我使用Finchley. RC2作为Spring云版本,sping-Cloud-starter-合同-存根-运行程序是我唯一的测试依赖项,而不是sping-boot-starter-test

我知道WireMock返回了错误的内容类型,因为我在Spring中深入调试了HttpMessageConverterExtractor类,getContentType方法在查询时就是这样返回的。

为什么WireMock返回了错误的内容类型,尽管它在日志中报告了正确的内容类型?我怎样才能让它正确地返回一个应用程序/json,这样我就可以反序列化我的简单消息了?

共有2个答案

傅星光
2023-03-14

我认为你应该把它作为一个问题提交WireMock。此外,您没有在请求显式中设置application/json content-type头。也许这是个问题?响应存根中的标题名不应该是content type吗?

羊毅庵
2023-03-14

我的问题和你完全一样。我通过添加

headers {
  header 'Content-Type': 'application/json;charset=UTF-8'
}

回应。你的回复中似乎有,虽然是用另一种方式写的,但这确实解决了我的问题。所以这和它有关。

在进行更改之前,curl没有显示Content-Type响应标头:

curl-v-H“Accept:application/json”localhost:6565/products/ABC
*正在尝试127.0.0.1
*TCP_节点延迟设置
*连接到本地主机(127.0.0.1)端口6565(#0)
GET/products/ABC HTTP/1.1
主机:本地主机:6565
用户代理:curl/7.58.0
接受:应用程序/json

HTTP/1.1 200 OK
传输编码:分块
服务器:Jetty(9.2. z-SNAPSHOT)

连接#0到主机localhost完好无损

{  
  "price": {  
    "currencyCode": "EUR",  
    "value": "100.50"  
  },  
  "name": "Fake product"  
}

完成更改后,curl返回了此项,RestTemboard设法对其进行了反序列化。

HTTP/1.1 200 OK
内容类型:application/json;charset=UTF-8传输编码:分块
服务器:Jetty(9.2.z-SNAPSHOT)

这是我的工作合同:

import org.springframework.cloud.contract.spec.Contract
Contract.make {
    description "should return product information"
    request{
        method GET()
        url("/products/ABC")
    }
    response {
        status 200
        headers {
            header 'Content-Type': 'application/json;charset=UTF-8'
    }
        body([
          name: 'Fake product',
          price:[
              currencyCode: 'EUR',
              value: 100.50
          ]
        ])
    }
}

希望这有帮助

 类似资料:
  • 我有下面的课,我试图测试。我遇到问题的方法是,因为我试图存根/模拟行为,然后在测试中验证行为。

  • 当通过负载平衡的RestTemboard发送https请求时,我收到以下堆栈跟踪: 如何配置Spring Cloud Contract Stub Runner,使我的Spring Cloud Stub能够通过HTTPS访问?

  • 问题内容: 我正在学习Java。我试图运行代码,但出现此错误:。它向我显示错误的代码部分。 为什么会这样呢? 问题答案: 这是因为在类中不能有两个具有相同名称但返回类型不同的方法。 子类不能使用与返回类型不同的超类中已经存在的方法相同的名称声明方法。 但是,子类可以声明具有与超类相同的签名的方法。我们称此为“覆盖”。 你需要这个 要么 一个好的做法是通过注释标记覆盖的方法:

  • 我试图使用第三方Web服务(基于php)在asp.netc#应用程序,但失败的服务配置。已经尝试添加服务/Web引用-所有相同的错误: 响应消息的内容类型 text/html 与绑定的内容类型不匹配(text/xml;charset=utf-8)。如果使用自定义编码器,请确保正确实现 IsContentTypeSupport 方法。响应的前 402 个字节是:” [已手动编辑响应以正确显示 对我来

  • 我刚刚开始使用Wiremck,我有一个关于存根的问题。 从文档中可以看出,您可以在映射下使用JSON文件,也可以在Java代码中使用代码)。然而,我发现使用)会导致Wiremock控制台中出现“请求不匹配”消息。 这是正确的行为吗?存根需要代码和json文件吗? 谢谢

  • 我来这里是因为我还没有找到解决问题的办法。我实际上是在尝试用wiremock来存根一个响应(对模拟服务的调用是通过假装客户端完成的)。我的意图是在真实的假客户机上得到虚假的响应,不是在测试中,而是在真实的应用程序中。因此,在本例中,我不是在测试中截取WireMock服务器,而是在spring boot应用程序类中,然而,在截取响应时,我遇到了一个非常奇怪的错误,到目前为止,我已经调查了很多次,但都