• Spring Cloud Contract简介


    转载:https://www.jianshu.com/p/e3277824a10a

    和dummy service一样

    Spring Cloud Contract是个啥?

    Spring Cloud Contract 为通过CDC(Customer Driven Contracts)开发基于JVM的应用提供了支持。它为TDD(测试驱动开发)提供了一种新的测试方式 - 基于接口。

    为什么要使用契约做测试?

    试想一下,如果你所在的项目在使用微服务架构,各个服务之间存在调用关系如下:

    微服务之间调用

    当你想专注测试某一个服务时,需要将其他的服务都起起来,才能进行测试。或者,写大量的集成测试,将外部的所有服务调用都mock掉。
    这两种方式的测试的成本都很高。那么怎么解决这个问题?
    答案就是:契约测试

    • 契约测试的优势
      一旦服务和服务之间定义了契约,Spring cloud contract会为服务消费端提供stub的mock server,这样,用户就可以只关注自己的服务进行测试,同时也不需要写大量的集成测试。


      契约测试
    • 契约测试适用的场景
      并不是所有的场景都适用,如果该服务并没有太多的外部调用依赖,那其实并没有写契约测试的必要。只有当服务的依赖很多,同时依赖的系统特别多的时候,契约测试才会适用。

    • 契约测试的使用成本
      契约的优势在于,当上下游之间签订了契约后,任意一方对契约进行了修改,另外一方就能知道。但是,如果只是单边加了契约测试,其实意义不是很大,充其量只是个可测试的api文档。
      在使用的过程中,当有复杂的业务场景是,我们常常会因为需要mock很多的数据,而需要花很长的时间去准备测试数据,为此可能需要写很多的契约。

    如何定义契约呢?

    Spring Cloud Contract现在支持2种格式 yaml和groovy。
    groovy灵活性比较高,但是上手成本有点高。

    org.springframework.cloud.contract.spec.Contract.make {
        request {
            method 'PUT'
            url '/api/12'
            headers {
                header 'Content-Type': 'application/vnd.org.springframework.cloud.contract.verifier.twitter-places-analyzer.v1+json'
            }
            body '''
            [{
                "created_at": "Sat Jul 26 09:38:57 +0000 2014",
                "id": 492967299297845248,
                "id_str": "492967299297845248",
                "text": "Gonna see you at Warsaw",
                "place":
                {
                    "attributes":{},
                    "bounding_box":
                    {
                        "coordinates":
                            [[
                                [-77.119759,38.791645],
                                [-76.909393,38.791645],
                                [-76.909393,38.995548],
                                [-77.119759,38.995548]
                            ]],
                        "type":"Polygon"
                    },
                    "country":"United States",
                    "country_code":"US",
                    "full_name":"Washington, DC",
                    "id":"01fbe706f872cb32",
                    "name":"Washington",
                    "place_type":"city",
                    "url": "http://api.twitter.com/1/geo/id/01fbe706f872cb32.json"
                }
            }]
        '''
        }
        response {
            status OK()
        }
    }
    

    yaml上手比较简单,但是,对于复杂的契约支持稍微弱一点。

    description: Some description
    name: some name
    priority: 8
    ignored: true
    request:
      url: /foo
      queryParameters:
        a: b
        b: c
      method: PUT
      headers:
        foo: bar
        fooReq: baz
      body:
        foo: bar
      matchers:
        body:
          - path: $.foo
            type: by_regex
            value: bar
        headers:
          - key: foo
            regex: bar
    response:
      status: 200
      headers:
        foo2: bar
        foo3: foo33
        fooRes: baz
      body:
        foo2: bar
        foo3: baz
        nullValue: null
      matchers:
        body:
          - path: $.foo2
            type: by_regex
            value: bar
          - path: $.foo3
            type: by_command
            value: executeMe($it)
          - path: $.nullValue
            type: by_null
            value: null
        headers:
          - key: foo2
            regex: bar
          - key: foo3
            command: andMeToo($it)
    

    我个人还是比较倾向于使用yaml,主要还是因为yaml语法比较简单,同时,对于90%的契约,其实都是简单型契约,很少会遇到复杂的使用场景,如果你要写一个特别复杂的契约,可能你就需要好好想想如何简化这个契约了。

    契约只要组成部分就是 request(method,url,body,headers),response(status,body),我们比较常用的方式是 将request的body和response的body定义成2个json文件,然后,使用fromFile方法直接引用。
    groovy 写法

    import org.springframework.cloud.contract.spec.Contract
    
    Contract.make {
        request {
            method('PUT')
            headers {
                contentType(applicationJson())
            }
            body(file("request.json"))
            url("/1")
        }
        response {
            status OK()
            body(file("response.json"))
            headers {
                contentType(textPlain())
            }
        }
    }
    

    yaml写法

    request:
      method: GET
      url: /foo
      bodyFromFile: request.json
    response:
      status: 200
      bodyFromFile: response.json
    

    request.json

    { "status" : "REQUEST" }
    

    response.json

    { "status" : "RESPONSE" }
    

    附上源码:https://github.com/huleTW/spring-contract-yaml-demo/tree/master

  • 相关阅读:
    实验一 开发环境的熟悉 20165311
    2018-2019-2 20165307《网络对抗技术》Exp9 Web安全基础
    2018-2019-2 网络对抗技术 20165307 Exp 8 Web基础
    2018-2019-2 网络对抗技术 20165307 Exp7 网络欺诈防范
    2018-2019-2 20165307网络对抗技术 Exp6:信息收集与漏洞扫描
    2018-2019-2 20165307《网络对抗技术》Exp5 MSF基础应用
    2018-2019-2 网络对抗技术 20165307 Exp4 恶意代码分析
    2018-2019-2 网络对抗技术 20165307 Exp3 免杀原理与实践
    2018-2019-2 20165307《网络对抗技术》Exp2 后门原理与实践
    20165307《网络对抗技术》Exp1 PC平台逆向破解
  • 原文地址:https://www.cnblogs.com/xiang--liu/p/11422170.html
Copyright © 2020-2023  润新知