effective testing with api simulation and (micro)service ... · effective testing with api...

66
@mogronalol | @danielbryantuk Effective Testing with API Simulation and (Micro)Service Virtualisation 1 Andrew Morgan | Daniel Bryant @mogronalol | @danielbryantuk @Spectolabs

Upload: others

Post on 20-May-2020

12 views

Category:

Documents


1 download

TRANSCRIPT

@mogronalol | @danielbryantuk

Effective Testing with API Simulation and (Micro)Service Virtualisation

1

Andrew Morgan | Daniel Bryant @mogronalol | @danielbryantuk

@Spectolabs

@mogronalol | @danielbryantuk 2

tl;dr

• Testing distributed systems is hard

• Many of us building distributed systems (microservices)

• API simulation is a new (old) tool to help with testing

@mogronalol | @danielbryantuk 3

About Us

• Independent Consultant • Microservices / Cloud /

Continuous Delivery • InfoQ Editor

Andrew Morgan @mogronalol

Daniel Bryant @danielbryantuk

• Consultant/CTO SpectoLabs • Cloud, containers, and

microservices • O’Reilly book on the way!

@mogronalol | @danielbryantuk 5

Agenda

• The problems with testing API driven architectures • Introduction to API simulation • Applying API simulation patterns • Data management • Conclusion

@mogronalol | @danielbryantuk 6

Agenda

• The problems with testing API driven architectures • Introduction to API simulation • Applying API simulation patterns • Data management • Conclusion

@mogronalol | @danielbryantuk

API-Driven Architecture

7

Application

Payment Provider

Social Network

API Call API Call

@mogronalol | @danielbryantuk

Microservices

8

Payment

Company

Booking

Flights

Auth

@mogronalol | @danielbryantuk

A natural evolution...

9

@mogronalol | @danielbryantuk

Challenges…

10

@mogronalol | @danielbryantuk 11

Airline Booking Application

• Microservice architecture • Integration with third party services • Integration with legacy internal services • Heavy resource consumption • A standard CI/CD pipeline

@mogronalol | @danielbryantuk 12

Resources

Booking

Flights

Rewards

Payments

Fraud

Cost

@mogronalol | @danielbryantuk 13

@mogronalol | @danielbryantuk 14

Licensing

Consumer

Producer

Consumer

Producer

Third party Cost

@mogronalol | @danielbryantuk

ConsumerConsumer

15

Rate Limiting

Producer

Consumer

Rate Limited ProducerProducer

@mogronalol | @danielbryantuk 16

Flakey Dependencies

Consumer

Producer

Consumer

Producer

Consumer

Producer

@mogronalol | @danielbryantuk 17

Doesn't exist

Consumer

?

@mogronalol | @danielbryantuk 18

Non Deterministic

assertThat(booking.getDate()) .isEqualTo(LocalDate.of(2013,1,8));

Consumer

Booking Service

Consumer

Booking Service

Consumer

Booking Service {

“date” : “2013-01-08”, … }

{

“date” : “2016-02-07”, … }

@mogronalol | @danielbryantuk 19

Fault Injection

Consumer

Producer

Consumer

Producer

4xx, 5xx, timeouts

Operationally challenging to trigger

faults

@mogronalol | @danielbryantuk 20

Agenda

• The problems with testing API driven architectures • Introduction to API simulation • Applying API simulation patterns • Data management • Conclusion

@mogronalol | @danielbryantuk 21

API Simulation

• Emulation of real API • Non-intrusive • Lightweight - or should be

@mogronalol | @danielbryantuk 22

Open Source Tooling

@mogronalol | @danielbryantuk

Capture ModeSimulate Mode

Intercept and store requests & responses

23

Architecture

Consumer Producer

Replay recorded requests & responses

@mogronalol | @danielbryantuk 24

Creating Data

@mogronalol | @danielbryantuk 25

Creating Data

@mogronalol | @danielbryantuk 26

Forward Proxy

Consumer Producer

Proxy Setting

@mogronalol | @danielbryantuk 27

Reverse Proxy

Consumer Producer

Reverse Proxy SettingPoints to Hoverfly

@mogronalol | @danielbryantuk 28

Not Mocking

Service Under Test

Mocking

Dependant Service

Http

Virtual Service

Mocks bleed into the architectural boundary of

your application

@mogronalol | @danielbryantuk 29

Agenda

• The problems with testing API driven architectures • Introduction to API simulation • Applying API simulation patterns • Data management • Conclusion

@mogronalol | @danielbryantuk 30

Record and replay

Consumer External Producer

Intercept &

Simulate

@mogronalol | @danielbryantuk 31

JUnit Example

@Rule public HoverflyRule hoverflyRule = HoverflyRule.inCaptureMode(“src/test/resources/external.json”);

@Testpublic void shouldBeAbleToRetrieveABooking() throws URISyntaxException { // Given final int bookingId = 1; // When final Booking booking = bookingServiceGateway.getBooking(bookingId); // Then assertThat(booking.getCustomer()).isEqualTo(“Andrew Morgan”); assertThat(booking.getDate()).isEqualTo(LocalDate.of(2016,3,1));}

@mogronalol | @danielbryantuk 32

JUnit Example{ "data": [ { "request": { "path": "/api/bookings/1", "method": "GET", "destination": "www.my-test.com", "query": null, "body": "" }, "response": { "status": 200, "body": “{\”customer\”:\”Andrew Morgan\", \”date\”: \”2016-03-01\”}}}”, "headers": { "Content-Type": [ "application/json" ] } } } ]}

@mogronalol | @danielbryantuk 33

JUnit Example

@Testpublic void shouldBeAbleToRetrieveABooking() throws URISyntaxException { // Given final int bookingId = 1; // When final Booking booking = bookingServiceGateway.getBooking(bookingId); // Then assertThat(booking.getCustomer()).isEqualTo(“Andrew Morgan”); assertThat(booking.getDate()).isEqualTo(LocalDate.of(2016,3,1));}

@Rule public HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode(classpath(“external.json”));

@mogronalol | @danielbryantuk 34

Advantages

• Isolation • Flaky dependencies • Rate limiting • Deterministic • Licensing

@mogronalol | @danielbryantuk 35

Operations

Consumer External Producer

Virtual Service

Internal Producer

Internal Producer

Internal Producer

Virtual Service

Virtual Service

Virtual Service

@mogronalol | @danielbryantuk 36

CLI Example

$ hoverctl start —proxy-port 8080 $ hoverctl import accounts-service-simulation.json

$ hoverctl start —proxy-port 8081 $ hoverctl import payments-service-simulation.json

$ curl http://www.account-service.com/api/v1/accounts/1 —proxy http://localhost:8080

[{"name":"foo"}]

$ curl http://www.payment-service.com/api/v1/payments/1 -proxy http://localhost:8081

[{“amount":"£23.27"}]

@mogronalol | @danielbryantuk 37

@mogronalol | @danielbryantuk

Matchers

Method Destination Path Query

GET www.foo.com /miss ?token=foo

GET www.foo.com /login ?token=foo

Request

GET www.foo.com /login ?token=foo

38

Matching

@mogronalol | @danielbryantuk

Matcher

Method Destination Path Query

GET www.foo.com /login ?token=foo

Request

GET www.foo.com /login ?token=foo

39

Why Looser Matching?

?token=miss???

@mogronalol | @danielbryantuk 40

Field Omission

Matcher

Method Destination Path Query

GET www.foo.com /login ?token=foo

Request

GET www.foo.com /login ?token=bar

@mogronalol | @danielbryantuk 41

Regex Matching

Matcher

Method Destination Path

GET www.foo.com /name/john

Request

GET www.foo.com /name/tim

name\\/(.*)

Path Regex

@mogronalol | @danielbryantuk 42

JSON Matching

Matcher

Body

{“foo” : “bar”}

Request

{“foo” : “bar”}

Body JSON

@mogronalol | @danielbryantuk

Matcher

Body JSON

{“foo” : “bar”, “not” : “important”}

Request

{“foo” : “bar”}

Body JSON loose=true

43

JSON Matching

@mogronalol | @danielbryantuk 44

Additional Matchers

• XML (Strict and Loose) • JSONPath / XPath • …Anything

@mogronalol | @danielbryantuk

Request

GET www.foo.com /name/tim ?token=bar

Matchers Match?

GET www.foo.com

GET www.foo.com /name/tim

GET www.foo.com /name/tim ?token=bar

45

Scoring

Score

2

3

4

@mogronalol | @danielbryantuk

Request

GET www.foo.com /name/tim ?token=bar

Matchers Score Match?

MISS www.foo.com miss 1

MISS www.foo.com /name/tim 2

GET www.foo.com /name/tim miss 3

46

Debugging

Closest?

@mogronalol | @danielbryantuk

Path Matcher Response Body

/name\\/(.*) {“name”:”john”}

Request Path Response Body

/name/john {“name”:”john”}

/name/peter {“name”:”john”}

47

Templating

{“name”:”{{ Request.Path.[1] }}”}

{“name”:”peter”}

@mogronalol | @danielbryantuk

Request Response

GET www.shopping.com/basket {}

POST www.shopping.com/basket {“item”:”eggs”} 200

GET www.shopping.com/basket {}

48

The Problem of State

@mogronalol | @danielbryantuk

Request Response Requires State

Transitions State

GET www.shopping.com/basket {} basket ==

empty

POST www.shopping.com/basket

{“item”:”eggs”} 200 basket =

eggs

GET www.shopping.com/basket

{“item”:”eggs”}

basket == eggs

49

State

@mogronalol | @danielbryantuk

Consumer

50

SSL Bump

Needs to Decrypt & Impersonate

SSL

Producer

SSL Again

MITM Attack

Generate Fake Self Signed Certificate

@mogronalol | @danielbryantuk 51

Fault Injection

Consumer External Producer

Middleware

@mogronalol | @danielbryantuk 52

Fault Injection

@mogronalol | @danielbryantuk 53

Agenda

• The problems with testing API driven architectures • Introduction to API simulation • Applying API simulation patterns • Data management • Conclusion

@mogronalol | @danielbryantuk 54

Stale Data

Consumer Virtual Service

Consumer Virtual Service

Consumer Real Service

@mogronalol | @danielbryantuk 55

Ownership

Own Consumer Own Producer Strategy

Integration Contract Testing

@mogronalol | @danielbryantuk 56

Integration Contract Testing

Scheduled Build

Reproduce Simulations Diff

No diff?

Diff?

Integration Testing or

Contract Diff

http://martinfowler.com/bliki/IntegrationContractTest.html

@mogronalol | @danielbryantuk 57

Ownership

Own Consumer Own Producer Strategy

Integration Contract Testing

Simulation as First Class Citizen

@mogronalol | @danielbryantuk 58

First Class Simulations

Run and Capture

Service Tests

Parse Contract

Transform to simulation

Parse Documentati

on

Publish Virtual Service

@mogronalol | @danielbryantuk 59

Ownership

Own Consumer Own Producer Strategy

Integration Contract Testing

Consumer Driven Contract Testing

Virtual Service as First Class Citizen

@mogronalol | @danielbryantuk 60

Consumer Driven Contracts

Consumer Defines Contract

Implement Producer

http://www.martinfowler.com/articles/consumerDrivenContracts.html

Generate Producer

Stubs

Generate Producer Contract

Tests

Implement Consumer

Run Consumer Contract

Tests

@mogronalol | @danielbryantuk 61

Consumer Driven Contracts

Change producer

http://www.martinfowler.com/articles/consumerDrivenContracts.html

Run Consumer Contract

Tests

@mogronalol | @danielbryantuk 62

Tools

@mogronalol | @danielbryantuk 63

Testing Pyramid

End to end

Integration / Service Testing

Unit Testing

Consumer Driven Contract Testing

@mogronalol | @danielbryantuk 64

Agenda

• The problems with testing API driven architectures • Introduction to API simulation • Applying API simulation patterns • Data management • Conclusion

@mogronalol | @danielbryantuk 65

Conclusion

• Reduced cost be replacing real resources • Improved deployment time with API simulations • Less dependance on end-to-end testing • Advanced patterns for simplifying API simulations • Improved feedback cycle

@mogronalol | @danielbryantuk

Questions?

66

@mogronalol | @danielbryantuk [email protected] | [email protected]

https://github.com/mogronalol hoverfly.io