Share
Embed
Transcript
56 slides
-
How to write a test for it ? Client Api
Request Response -
Problems •What happens if there is a change in the
real producer ? •The owner of the mock is the consumer •Not trustworthy -
Client Mock or Stub Api Test Real world Mocking !!!
Request Response The mock has nothing to do with the real API Client Real Service Api Request Response -
Problems •Slow •All services need to be up before running
the tests •Require a clean/dedicated integration environment -
#Questions It’s the consumer that uses the API. Would it
be possible that : • consumer takes part in the creation of the API of the producer ? • API changes be driven by consumers ? -
“An integration test is a test between an API provider
and an API consumer that asserts that the provider returns expected responses for a set of pre-defined requests by the consumer. The set of pre-defined requests and expected responses is called a contract.” -
Glossary •Producer Service that exposes an API. •Consumer Service that
consumes the API of the producer. •Contract Agreement between producer and consumer on how the API will look like. •Consumer Driven Contracts Approach where the consumer drives the changes of the API of the producer. -
As a developer I want to confirm that the consumer
(client) and the provider (service) can understand each others So that I can check they are compatibles -
How to ? Define API contract on the consumer side.
The contract must be enforced on the service provider. -
1) Start With Consumer • Write Test(S) • Define interactions
/ Expectations • In your favorite language -
1) Start With Consumer • Run Tests • From Expectations
TO Contract • Json File -
2) Contract Driven Development • Design Your API From The
Contract • Write A RED Test -
• Git ? • Near from the Provider sources ?
• Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ? -
Pact Broker • A RESTful API for publishing and retrieving
pacts. • An embedded API browser for navigating the API. • Displays provider verification results so you know if you can deploy safely. • Auto-generated documentation for each pact. • Provides a "matrix" of compatible consumer and provider versions, so you know which versions can be safely deployed together. • Dynamically generated network diagrams so you can visualise your microservice network. • Provides badges to display pact verification statuses in your READMEs. • Enables an application version to be tagged (ie. "prod", "feat/customer-preferences") to allow repository-like workflows. • Provides webhooks to trigger actions when pacts change eg. run provider build, notify a Slack channel. • View diffs between Pact versions so you can tell what expectations have changed. • Docker Pact Broker • A CLI for encorporating the Pact workflow into your continuous integration process. https://github.com/pact-foundation/pact_broker -
A RESTful API for publishing and retrieving pacts. An embedded
API browser for navigating the API. Displays provider verification results so you know if you can deploy safely. -
Auto-generated documentation for each pact. Provides a "matrix" of compatible
consumer and provider versions, -
Dynamically generated network diagrams so you can visualise your microservice
network. sheriff hopper -
A CLI for encorporating the Pact workflow into your continuous
integration process. Docker Pact Broker -
Provides webhooks to trigger actions when pacts change eg. run
provider build, notify a Slack channel. https://github.com/pact-foundation/pact_broker/blob/master/lib/pact_broker/doc/views/webhooks.markdown -
Strengths Opportunities Threats Weaknesses • Cross-languages • Easy integration with
a pact broker • Specification / standardization • 2 versions of the Specification ◦ 3.0 for JVM ◦ 2.0 for others • Api quality depends on the language • Where to store the Contracts ? (if no broker) • Yet another format (Not Open Api) • Start easily A CDC approach ◦ Only a few Jar to reference • Design First approach Wanted ? • Contract + Integration Tests ? https://github.com/agilepartner/pact-sandbox -
Spring Cloud Contract Doc Spring Cloud Contract is an umbrella
project holding solutions that help users in successfully implementing the Consumer Driven Contracts approach. Currently Spring Cloud Contract consists of the Spring Cloud Contract Verifier project. Spring Cloud Contract Verifier is a tool that enables Consumer Driven Contract (CDC) development of JVM-based applications. It is shipped with Contract Definition Language (DSL) written in Groovy or YAML. Spring Cloud Contract Verifier moves TDD to the level of software architecture. Contract definitions are used to produce following resources: • by default JSON stub definitions to be used by WireMock (HTTP Server Stub) when doing integration testing on the client code (client tests). Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier. • Messaging routes if you’re using one. We’re integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to. • Acceptance tests (by default in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (server tests). Full test is generated by Spring Cloud Contract Verifier. -
1) Define The Contract • Write contract in Groovy or
YML • Define Expectations org.springframework.cloud.contract.spec.Contract.make { description(""" Donuts API """) label("Get all donuts") request { method GET() url '/donuts' headers { contentType(applicationJson()) } } response { status OK() body( sugar: $(regex('[0-9]+')) , flour: $(regex('[0-9]+')) , butter: $(regex('[0-9]+')) ) headers { contentType(applicationJson()) } } } -
2) Contract Driven Development • Design Your API From The
Contract • Write A RED Test public abstract class ContractVerifierBase { @Before public void setup() { RestAssuredMockMvc.standaloneSetup(new DonutsController()); } } org.springframework.cloud.contract.spec.Contract.ma ke { description(""" Donuts API """) label("Get all donuts") request { method GET() url '/donuts' headers { contentType(applicationJson()) } } response { status OK() body( sugar: $(regex('[0-9]+')) , flour: $(regex('[0-9]+')) , butter: $(regex('[0-9]+')) ) headers { contentType(applicationJson()) } } } -
2) Contract Driven Development • Make You Test Pass /
GREEN @RestController public class DonutsController { @GetMapping(value = "/donuts", produces = "application/json") public ResponseEntity getDonuts() { return ResponseEntity.ok(Arrays.asList(new Donut(120, 150, 140))); } -
3) Generate a stub from contract • TODO Make You
Test Pass / GREEN @RestController public class DonutsController { @GetMapping(value = "/donuts", produces = "application/json") public ResponseEntity getDonuts() { return ResponseEntity.ok(Arrays.asList(new Donut(120, 150, 140))); } -
Strengths Opportunities Threats Weaknesses • Tests generated by the framework
• Stub generated • Contract DSL based • Not cross-languages • Dependency on Spring Cloud • Where to store the Contracts ? centralized jar ? • Yet another format. Open API is not directly supported • No dependency visualization • No central repository for contract • Start easily A CDC approach ◦ Only a few Jar to reference • Design First approach Wanted ? • Contract + Integration Tests ? https://github.com/wilvdb/contracts-lab -
• Git or jar ? • Near from the Provider
sources ? • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ? -
#Workshop • There is no more Donuts at Springfiled, and
Homer is going to be crazy if he cannot get any donuts for breakfast • Your mission : restart the donuts factory • https://github.com/wilvdb/contracts-lab ◦ Module docker : docker-compose up ◦ Module simpson-client-pact : mvn install → Load contract on pact broker ◦ Module donuts-factory-pact : complete DonutsController to validate the contract -
Apicurio Doc Apicurio Studio, maintained by the Red Hat Developer
Program, is a tool for designing APIs that follows the specification without requiring the developer(s) to be intimately familiar with it. It provides a GUI for defining all aspects of the API. Ultimately, Apicurio outputs both human and machine readable documentation which complies with the latest version of the OpenAPI specification. This walkthrough covers the process of designing an API with Apicurio from start to finish, and evaluates the possibility of using Apicurio in production. Features: • Support of OpenApi and Swagger • Project code generation (limited support to JAX-RS for the moment • Storage of contract on GIT • Microcks integration (mocking and integration testing tool) -
Microcks Doc Microcks helps providers of API and micro-services to
rapidly deliver : • A comprehensible vision of their API, exposing sample requests and responses as well as base functional rules (cases when API responds A or B or raises exceptions) • A set of testing environments to allow API consumers or System Under Tests to use API even if implementation is not finished! • Contract testing plans of their API, allowing them to run, record and compare contract tests run against different environments. -
Swagger Codegen Swagger Codegen can simplify your build process by
generating server stubs and client SDKs for any API, defined with the OpenAPI (formerly known as Swagger) specification, so your team can focus better on your API’s implementation and adoption. <plugin> <groupId>io.swagger.codegen.v3</groupId> <artifactId>swagger-codegen-maven-plugin</artifactId> <executions><execution> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.basedir}/src/main/resources/api.yml</inputSpec> <language>spring</language> <apiPackage>${default.package}.controller</apiPackage> <modelPackage>${default.package}.model.dto</modelPackage> <invokerPackage>${default.package}.handler</invokerPackage> <generateSupportingFiles>false</generateSupportingFiles> <generateApiTests>false</generateApiTests> <configOptions> <java8>true</java8> <interfaceOnly>true</interfaceOnly> </configOptions> </configuration> </execution></executions> </plugin> @Api(value = "pets", description = "the pets API") public interface PetsApi { @ApiOperation(value = "", nickname = "addPet", notes = "Creates a new pet in the store. Duplicates are allowed", response = Pet.class, tags={ }) @ApiResponses(value = { @ApiResponse(code = 200, message = "pet response", response = Pet.class), @ApiResponse(code = 200, message = "unexpected error", response = Error.class) }) @RequestMapping(value = "/pets", produces = { "application/json" }, consumes = { "application/json" }, method = RequestMethod.POST) default ResponseEntity<Pet> addPet(@ApiParam(value = "Pet to add to the store" ,required=true ) @Valid @RequestBody NewPet body) {...} -
#resources 7 reasons for consumer driven contracts Spring Cloud Contract
meet Pact Consumer driven contract testing using pact