Post on 26-Jan-2017
MOUNTEBANK AND YOUNagesh Kumarnkumar@thoughtworks.com
1
AGENDA
Integration TestingIsolation TestingReal ProblemMountebankQuick WatchWhom to Catch
2
Test multiple components at the same timeNo GUINo faking/mocking/stubbing/etcNeed Real things to Integrate WithReal Services must be reliable and need to be fast
THE CLASSICAL VIEW OF INTEGRATION TESTING
3
THE CLASSICAL VIEW OF ISOLATION TESTING
4
Test as many real components at the same timeStub out the unreliable Real DependencyStub out the non-existing Real DependencyTesting our code while isolating it from the naughty Real Dependency
YOU CAN’T ALWAYS FIX THE REAL PROBLEM (SAD, BUT TRUE)
5
Real Things being maintained/developed by other teamsPoor testing environment (Hardware, Data, Other)Fixing the Real Thing is more costly than enduring itClient won’t pay us to fix the Real Things
WHAT IS MOUNTEBANK?
“mountebank is the first tool to provide
cross-platform, multi-protocol test doubles over the
wire.”
- mountebank
6
http://www.mbtest.org/
WHY MOUNTEBANK?
ProprietaryLacked platform supportLacked protocol supportNot extensibleSlowHard to run during unit test cycleManaged through a special IDE
7
Existing tools were:
WHAT CAN IT DO FOR ME?
Record live requests and responses to replay laterImitate a response from scratchRespond to specific requests via predicatesTrack any requests that come its way
8
AN OVERVIEW OF MOUNTEBANK IN ACTION
System Under Test
Tests
Mountebank
Stub
WHAT DO I NEED TO KNOW IN MB?
ImpostersPredicatesProxies Injection Behaviors
10
WHAT ARE IMPOSTERS?
The imposter is the most integral part of mountebank. An
imposter is associated with a
port number and a protocol. It contains
within itself the response we want
to return, and other related information.
11
http://www.mbtest.org/docs/api/stubs
ANATOMY OF AN IMPOSTERPOST /imposters HTTP/1.1Host: localhost:2525Accept: application/jsonContent-Type: application/json
{ "port": 4545, "protocol": “http", "stubs": [ { "responses": [ { "is": { "statusCode": 200, (Will default to 200 if not provided) “headers": { “Content-Type": “text/plain“ }, "body": “Hello world!” } } ] } ]}
12
ANOTHER IMPOSTER EXAMPLEPOST /imposters HTTP/1.1Host: localhost:2525Accept: application/jsonContent-Type: application/json
{ "port": 4546, "protocol": "http", "stubs": [ { "responses": [ { "is": { "statusCode": 201, “headers": { “Content-Type": “text/plain“ }, "body": “Created!” } }, { "is": { "statusCode": 400, “headers": { “Content-Type": “text/plain“ }, "body": “ERROR: Already Exists!” } } ] } ]}
13
WHAT IS A PREDICATE?
The predicate is the part of an imposter which determines if a request should be
responded to by said imposter.
14
http://www.mbtest.org/docs/api/predicates
TYPES OF PREDICATES
Equals Deep Equals ContainsStarts/EndsWithMatches Exists Not/And/Or Injecthttp://www.mbtest.org/docs/api/predicates
15
WHAT CAN A PREDICATE OPERATE ON?
That depends on the protocol you’re using! For example, Http allows you to use predicates on: - Method Type - Query Path - Request Body - And More!
16
http://www.mbtest.org/docs/protocols/http
PREDICATE EXAMPLE{ "port": 4551, "protocol": "http", "stubs": [ { "responses": [ { "is": { "statusCode": 201, "headers": { "Content-Type": "text/plain" }, "body": "You posted to me!" } } ], "predicates": [ { "equals": { "method": "POST" } } ] } ]}
17
OR EXAMPLE{ "port": 4552, "protocol": "http", "stubs": [ { "responses": [ { "is": { "statusCode": 201, "headers": { "Content-Type": "text/plain" }, "body": "You posted to me!" } } ], "predicates": [ { "or": [ { "equals": { "method": "POST" } }, { "equals": { "method": "PUT" } } ] } ] } ]}
18
WHAT IS A PROXY?
The proxy is a special imposter
which allows us to get between our application and a
service it communicates with. It records each request,
forwards it to the service, and records the
response from that service. 19
http://www.mbtest.org/docs/api/proxies
BUT WHAT DO I DO WITH IT?
Record responses that would be difficult (if not impossible) to write by handLook at requests to see what distinguishes them from each other
20
PROXY EXAMPLE{ "port": 4560, "protocol": "http", "name": "duckduckgo", "stubs": [ { "responses": [ { "proxy": { "to": "http://api.duckduckgo.com/", "mode": "proxyOnce", "predicateGenerators": [ { "matches": { "method": true, "path": true, "query": true } } ] } } ] } ]}
21
Direct all Suggestions to Brandon (bbyars@thoughtworks.com)
THANK YOU