Files
spring-cloud-contract/reference/html/verifier_stubrunner.html
2019-07-31 00:23:56 +00:00

431 lines
17 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.7.1">
<title>Spring Cloud Contract Stub Runner</title>
<link rel="stylesheet" href="css/spring.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.hidden {
display: none;
}
.switch {
border-width: 1px 1px 0 1px;
border-style: solid;
border-color: #7a2518;
display: inline-block;
}
.switch--item {
padding: 10px;
background-color: #ffffff;
color: #7a2518;
display: inline-block;
cursor: pointer;
}
.switch--item:not(:first-child) {
border-width: 0 0 0 1px;
border-style: solid;
border-color: #7a2518;
}
.switch--item.selected {
background-color: #7a2519;
color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
$('.primary').each(function() {
primary = $(this);
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
primary.children('.title').remove();
});
$('.secondary').each(function(idx, node) {
secondary = $(node);
primary = findPrimary(secondary);
switchItem = createSwitchItem(secondary, primary.children('.switch'));
switchItem.content.addClass('hidden');
findPrimary(secondary).append(switchItem.content);
secondary.remove();
});
}
function createBlockSwitch(primary) {
blockSwitch = $('<div class="switch"></div>');
primary.prepend(blockSwitch);
return blockSwitch;
}
function findPrimary(secondary) {
candidate = secondary.prev();
while (!candidate.is('.primary')) {
candidate = candidate.prev();
}
return candidate;
}
function createSwitchItem(block, blockSwitch) {
blockName = block.children('.title').text();
content = block.children('.content').first().append(block.next('.colist'));
item = $('<div class="switch--item">' + blockName + '</div>');
item.on('click', '', content, function(e) {
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
e.data.siblings('.content').addClass('hidden');
e.data.removeClass('hidden');
});
blockSwitch.append(item);
return {'item': item, 'content': content};
}
$(addBlockSwitches);
</script>
</head>
<body class="book toc2 toc-left">
<div id="header">
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_spring_cloud_contract_stub_runner">Spring Cloud Contract Stub Runner</a>
<ul class="sectlevel2">
<li><a href="#_snapshot_versions">Snapshot versions</a></li>
<li><a href="#publishing-stubs-as-jars">Publishing Stubs as JARs</a></li>
<li><a href="#_common">Common</a></li>
<li><a href="#stubrunner-docker">Stub Runner Docker</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="_spring_cloud_contract_stub_runner"><a class="link" href="#_spring_cloud_contract_stub_runner">Spring Cloud Contract Stub Runner</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>One of the issues that you might encounter while using Spring Cloud Contract Verifier is
passing the generated WireMock JSON stubs from the server side to the client side (or to
various clients). The same takes place in terms of client-side generation for messaging.</p>
</div>
<div class="paragraph">
<p>Copying the JSON files and setting the client side for messaging manually is out of the
question. That is why we introduced Spring Cloud Contract Stub Runner. It can
automatically download and run the stubs for you.</p>
</div>
<div class="sect2">
<h3 id="_snapshot_versions"><a class="link" href="#_snapshot_versions">Snapshot versions</a></h3>
<div class="paragraph">
<p>Add the additional snapshot repository to your <code>build.gradle</code> file to use snapshot
versions, which are automatically uploaded after every successful build:</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml"></code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-groovy hljs" data-lang="groovy"></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="publishing-stubs-as-jars"><a class="link" href="#publishing-stubs-as-jars">Publishing Stubs as JARs</a></h3>
<div class="paragraph">
<p>The easiest approach would be to centralize the way stubs are kept. For example, you can
keep them as jars in a Maven repository.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
For both Maven and Gradle, the setup comes ready to work. However, you can customize
it if you want to.
</td>
</tr>
</table>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;!-- First disable the default jar setup in the properties section --&gt;
&lt;!-- Next add the assembly plugin to your build --&gt;
&lt;!-- Finally setup your assembly. Below you can find the contents of src/main/assembly/stub.xml --&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-groovy hljs" data-lang="groovy"></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_common"><a class="link" href="#_common">Common</a></h3>
<div class="paragraph">
<p>This section briefly describes common properties, including:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#common-properties-junit-spring">Common Properties for JUnit and Spring</a></p>
</li>
<li>
<p><a href="#stub-runner-stub-ids">Stub Runner Stubs IDs</a></p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="common-properties-junit-spring"><a class="link" href="#common-properties-junit-spring">Common Properties for JUnit and Spring</a></h4>
<div class="paragraph">
<p>You can set repetitive properties by using system properties or Spring configuration
properties. Here are their names with their default values:</p>
</div>
<table class="tableblock frame-topbot grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Property name</th>
<th class="tableblock halign-left valign-top">Default value</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.minPort</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">10000</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a port for a started WireMock with stubs.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.maxPort</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">15000</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a port for a started WireMock with stubs.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.repositoryRoot</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Maven repo URL. If blank, then call the local maven repo.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.classifier</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubs</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Default classifier for the stub artifacts.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.stubsMode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">CLASSPATH</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The way you want to fetch and register the stubs</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.ids</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Array of Ivy notation stubs to download.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.username</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional username to access the tool that stores the JARs with
stubs.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.password</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional password to access the tool that stores the JARs with
stubs.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.stubsPerConsumer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Set to <code>true</code> if you want to use different stubs for
each consumer instead of registering all stubs for every consumer.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stubrunner.consumerName</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If you want to use a stub for each consumer and want to
override the consumer name just change this value.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="stub-runner-stub-ids"><a class="link" href="#stub-runner-stub-ids">Stub Runner Stubs IDs</a></h4>
<div class="paragraph">
<p>You can provide the stubs to download via the <code>stubrunner.ids</code> system property. They
follow this pattern:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">groupId:artifactId:version:classifier:port</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that <code>version</code>, <code>classifier</code> and <code>port</code> are optional.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If you do not provide the <code>port</code>, a random one will be picked.</p>
</li>
<li>
<p>If you do not provide the <code>classifier</code>, the default is used. (Note that you can
pass an empty classifier this way: <code>groupId:artifactId:version:</code>).</p>
</li>
<li>
<p>If you do not provide the <code>version</code>, then the <code>+</code> will be passed and the latest one is
downloaded.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>port</code> means the port of the WireMock server.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Starting with version 1.0.4, you can provide a range of versions that you
would like the Stub Runner to take into consideration. You can read more about the
<a href="https://wiki.eclipse.org/Aether/New_and_Noteworthy#Version_Ranges">Aether versioning
ranges here</a>.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="stubrunner-docker"><a class="link" href="#stubrunner-docker">Stub Runner Docker</a></h3>
<div class="paragraph">
<p>We&#8217;re publishing a <code>spring-cloud/spring-cloud-contract-stub-runner</code> Docker image
that will start the standalone version of Stub Runner.</p>
</div>
<div class="paragraph">
<p>If you want to learn more about the basics of Maven, artifact ids,
group ids, classifiers and Artifact Managers, just click here <a href="#docker-project">[docker-project]</a>.</p>
</div>
<div class="sect3">
<h4 id="_how_to_use_it"><a class="link" href="#_how_to_use_it">How to use it</a></h4>
<div class="paragraph">
<p>Just execute the docker image. You can pass any of the <a href="#common-properties-junit-spring">Common Properties for JUnit and Spring</a>
as environment variables. The convention is that all the
letters should be upper case. The camel case notation should
and the dot (<code>.</code>) should be separated via underscore (<code>_</code>). E.g.
the <code>stubrunner.repositoryRoot</code> property should be represented
as a <code>STUBRUNNER_REPOSITORY_ROOT</code> environment variable.</p>
</div>
</div>
<div class="sect3">
<h4 id="_example_of_client_side_usage_in_a_non_jvm_project"><a class="link" href="#_example_of_client_side_usage_in_a_non_jvm_project">Example of client side usage in a non JVM project</a></h4>
<div class="paragraph">
<p>We&#8217;d like to use the stubs created in this <a href="#docker-server-side">[docker-server-side]</a> step.
Let&#8217;s assume that we want to run the stubs on port <code>9876</code>. The NodeJS code
is available here:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-bash hljs" data-lang="bash">$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs
$ cd bookstore</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s run the Stub Runner Boot application with the stubs.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-bash hljs" data-lang="bash"># Provide the Spring Cloud Contract Docker version
$ SC_CONTRACT_DOCKER_VERSION="..."
# The IP at which the app is running and Docker container can reach it
$ APP_IP="192.168.0.100"
# Spring Cloud Contract Stub Runner properties
$ STUBRUNNER_PORT="8083"
# Stub coordinates 'groupId:artifactId:version:classifier:port'
$ STUBRUNNER_IDS="com.example:bookstore:0.0.1.RELEASE:stubs:9876"
$ STUBRUNNER_REPOSITORY_ROOT="http://${APP_IP}:8081/artifactory/libs-release-local"
# Run the docker with Stub Runner Boot
$ docker run --rm -e "STUBRUNNER_IDS=${STUBRUNNER_IDS}" -e "STUBRUNNER_REPOSITORY_ROOT=${STUBRUNNER_REPOSITORY_ROOT}" -e "STUBRUNNER_STUBS_MODE=REMOTE" -p "${STUBRUNNER_PORT}:${STUBRUNNER_PORT}" -p "9876:9876" springcloud/spring-cloud-contract-stub-runner:"${SC_CONTRACT_DOCKER_VERSION}"</code></pre>
</div>
</div>
<div class="paragraph">
<p>What&#8217;s happening is that</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a standalone Stub Runner application got started</p>
</li>
<li>
<p>it downloaded the stub with coordinates <code>com.example:bookstore:0.0.1.RELEASE:stubs</code> on port <code>9876</code></p>
</li>
<li>
<p>it got downloaded from Artifactory running at <code><a href="http://192.168.0.100:8081/artifactory/libs-release-local" class="bare">http://192.168.0.100:8081/artifactory/libs-release-local</a></code></p>
</li>
<li>
<p>after a while Stub Runner will be running on port <code>8083</code></p>
</li>
<li>
<p>and the stubs will be running at port <code>9876</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>On the server side we built a stateful stub. Let&#8217;s use curl to assert
that the stubs are setup properly.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-bash hljs" data-lang="bash"># let's execute the first request (no response is returned)
$ curl -H "Content-Type:application/json" -X POST --data '{ "title" : "Title", "genre" : "Genre", "description" : "Description", "author" : "Author", "publisher" : "Publisher", "pages" : 100, "image_url" : "https://d213dhlpdb53mu.cloudfront.net/assets/pivotal-square-logo-41418bd391196c3022f3cd9f3959b3f6d7764c47873d858583384e759c7db435.svg", "buy_url" : "https://pivotal.io" }' http://localhost:9876/api/books
# Now time for the second request
$ curl -X GET http://localhost:9876/api/books
# You will receive contents of the JSON</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If you want use the stubs that you have built locally, on your host,
then you should pass the environment variable <code>-e STUBRUNNER_STUBS_MODE=LOCAL</code> and mount
the volume of your local m2 <code>-v "${HOME}/.m2/:/root/.m2:ro"</code>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="js/tocbot/tocbot.min.js"></script>
<script type="text/javascript" src="js/toc.js"></script>
<link rel="stylesheet" href="js/highlight/styles/atom-one-dark-reasonable.min.css">
<script src="js/highlight/highlight.min.js"></script>
<script>hljs.initHighlighting()</script>
</body>
</html>