46
README.adoc
46
README.adoc
@@ -147,6 +147,49 @@ public class WiremockForDocsClassRuleTests {
|
||||
|
||||
The use `@ClassRule` means that the server will shut down after all the methods in this class.
|
||||
|
||||
== Relaxed SSL Validation for Rest Template
|
||||
|
||||
WireMock allows you to stub a "secure" server with an "https" URL protocol. If your application wants to
|
||||
contact that stub server in an integration test, then it will find that the SSL certificates are not
|
||||
valid (it's the usual problem with self-installed certificates). The best option is often to just
|
||||
re-configure the client to use "http", but if that's not open to you then you can ask Spring to configure
|
||||
an HTTP client that ignores SSL validation errors (just for tests).
|
||||
|
||||
To make this work with minimum fuss you need to be using the Spring Boot `RestTemplateBuilder` in your app,
|
||||
e.g.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
----
|
||||
|
||||
This is because the builder is passed through callbacks to initalize it, so the SSL validation can be set up
|
||||
in the client at that point. This will happen automatically in your test if you are using the
|
||||
`@AutoConfigureWireMock` annotation (or the stub runner). If you are using the JUnit `@Rule` approach you need
|
||||
to add the `@AutoConfigureHttpClient` annotation as well:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest("app.baseUrl=https://localhost:6443")
|
||||
@AutoConfigureHttpClient
|
||||
public class WiremockHttpsServerApplicationTests {
|
||||
|
||||
@ClassRule
|
||||
public static WireMockClassRule wiremock = new WireMockClassRule(
|
||||
WireMockSpring.options().httpsPort(6443));
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
If you are using `spring-boot-starter-test` then you will have the Apache HTTP client on the classpath and it will
|
||||
be selected by the `RestTemplateBuilder` and configured to ignore SSL errors. If you are using the default `java.net`
|
||||
client you don't need the annotation (but it won't do any harm). There is no support currently for other clients, but
|
||||
it may be added in future releases.
|
||||
|
||||
== WireMock and Spring MVC Mocks
|
||||
|
||||
Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into a
|
||||
@@ -198,8 +241,7 @@ Spring Boot container if there is one.
|
||||
|
||||
https://projects.spring.io/spring-restdocs[Spring RestDocs] can be
|
||||
used to generate documentation (e.g. in asciidoctor format) for an
|
||||
HTTP API with https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#spring-mvc-test-framework[Spring MockMvc]
|
||||
or http://rest-assured.io/[RestAssured]. At the same time as you
|
||||
HTTP API with Spring MockMvc or RestEasy. At the same time as you
|
||||
generate documentation for your API, you can also generate WireMock
|
||||
stubs, by using Spring Cloud Contract WireMock. Just write your normal
|
||||
RestDocs test cases and use `@AutoConfigureRestDocs` to have stubs
|
||||
|
||||
@@ -63,9 +63,6 @@ class TestGenerator {
|
||||
}
|
||||
|
||||
int generate() {
|
||||
if (!configProperties.basePackageForTests) {
|
||||
|
||||
}
|
||||
generateTestClasses(configProperties.basePackageForTests)
|
||||
return counter.get()
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig
|
||||
@PackageScope
|
||||
class ClassBuilder {
|
||||
|
||||
private static final String SEPARATOR = "_REPLACEME_"
|
||||
|
||||
private final String className
|
||||
private final String packageName
|
||||
private final String baseClass
|
||||
@@ -70,7 +72,7 @@ class ClassBuilder {
|
||||
}
|
||||
|
||||
protected static String retrieveBaseClass(ContractVerifierConfigProperties properties, String includedDirectoryRelativePath) {
|
||||
String contractPackage = includedDirectoryRelativePath.replace(File.separator, '.')
|
||||
String contractPackage = includedDirectoryRelativePath.replace(File.separator, SEPARATOR)
|
||||
// package mapping takes super precedence
|
||||
if (properties.baseClassMappings) {
|
||||
Map.Entry<String, String> mapping = properties.baseClassMappings.find { String pattern, String fqn ->
|
||||
@@ -88,7 +90,7 @@ class ClassBuilder {
|
||||
}
|
||||
|
||||
private static String generateDefaultBaseClassName(String classPackage, ContractVerifierConfigProperties properties) {
|
||||
String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage).split("\\.")
|
||||
String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage).split(SEPARATOR)
|
||||
if (splitPackage.size() > 1) {
|
||||
String last = NamesUtil.capitalize(splitPackage[-1])
|
||||
String butLast = NamesUtil.capitalize(splitPackage[-2])
|
||||
|
||||
@@ -106,6 +106,6 @@ class NamesUtil {
|
||||
* Converts illegal package characters to underscores
|
||||
*/
|
||||
static String convertIllegalPackageChars(String packageName) {
|
||||
return packageName.replace('-', '_')
|
||||
return packageName.replaceAll('[_\\- .]', '_')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +60,12 @@ class ClassBuilderSpec extends Specification {
|
||||
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperpackageBase'
|
||||
}
|
||||
|
||||
def "should return a class from the generated path by when external contracts are picked"() {
|
||||
given:
|
||||
ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: "foo.Bar")
|
||||
String contractRelativeFolder = ["org","springframework","cloud","contract","verifier","tests","META_INF","com.example","hello_world","1.0.0"].join(File.separator)
|
||||
expect:
|
||||
ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'foo.Bar.Hello_world1_0_0Base'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.springframework.cloud.contract.verifier.util
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class NamesUtilTestSpec extends Specification {
|
||||
|
||||
def "should return the whole string before the last one"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
"a.b.c.d" == NamesUtil.beforeLast(string, ".")
|
||||
}
|
||||
|
||||
def "should return empty string when no token was found for before last"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
"" == NamesUtil.beforeLast(string, "/")
|
||||
}
|
||||
|
||||
def "should return first token after the last one"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
"e" == NamesUtil.afterLast(string, ".")
|
||||
}
|
||||
|
||||
def "should return the input string when no token was found for after last"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
string == NamesUtil.afterLast(string, "/")
|
||||
}
|
||||
|
||||
def "should return first token after the last dot"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
"e" == NamesUtil.afterLastDot(string)
|
||||
}
|
||||
|
||||
def "should return the input string when no token was found for after last dot"() {
|
||||
given:
|
||||
String string = "abcde"
|
||||
expect:
|
||||
string == NamesUtil.afterLastDot(string)
|
||||
}
|
||||
|
||||
def "should return camel case version of a string"() {
|
||||
given:
|
||||
String string = "BlaBlaBla"
|
||||
expect:
|
||||
"blaBlaBla" == NamesUtil.camelCase(string)
|
||||
}
|
||||
|
||||
def "should return capitalized version of a string"() {
|
||||
given:
|
||||
String string = "blaBlaBla"
|
||||
expect:
|
||||
"BlaBlaBla" == NamesUtil.capitalize(string)
|
||||
}
|
||||
|
||||
def "should return all text to last dot"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
"a.b.c.d" == NamesUtil.toLastDot(string)
|
||||
}
|
||||
|
||||
def "should return the input string when no token was found for to last dot"() {
|
||||
given:
|
||||
String string = "abcde"
|
||||
expect:
|
||||
string == NamesUtil.toLastDot(string)
|
||||
}
|
||||
|
||||
def "should convert a package notation to directory"() {
|
||||
given:
|
||||
String string = "a.b.c.d.e"
|
||||
expect:
|
||||
"a/b/c/d/e".replace("/", File.separator) == NamesUtil.packageToDirectory(string)
|
||||
}
|
||||
|
||||
def "should convert a directory notation to package"() {
|
||||
given:
|
||||
String string = "a/b/c/d/e".replace("/", File.separator)
|
||||
expect:
|
||||
"a.b.c.d.e" == NamesUtil.directoryToPackage(string)
|
||||
}
|
||||
|
||||
def "should convert all illegal package chars to legal ones"() {
|
||||
given:
|
||||
String string = "a-b c.1.0.x"
|
||||
expect:
|
||||
"a_b_c_1_0_x" == NamesUtil.convertIllegalPackageChars(string)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user