diff --git a/pom.xml b/pom.xml
index c4bfd7df..0ce67eff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,8 @@
spring.hateoas2.2.03.0.2
+ 4.12
+ 5.3.22.2.1Californium-SR41.7.25
@@ -550,7 +552,14 @@
junitjunit
- 4.12
+ ${junit.version}
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit-jupiter.version}test
diff --git a/src/test/java/org/springframework/hateoas/mediatype/LinkDiscovererStandardUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/LinkDiscovererStandardUnitTest.java
new file mode 100644
index 00000000..ba01db3b
--- /dev/null
+++ b/src/test/java/org/springframework/hateoas/mediatype/LinkDiscovererStandardUnitTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.hateoas.mediatype;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.springframework.hateoas.support.MappingUtils.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Optional;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.hateoas.Link;
+import org.springframework.hateoas.LinkRelation;
+import org.springframework.hateoas.Links;
+import org.springframework.hateoas.client.LinkDiscoverer;
+
+/**
+ * Standard collection of {@link LinkDiscoverer} tests.
+ *
+ * TODO: Merge with {@link org.springframework.hateoas.client.LinkDiscovererUnitTest}.
+ *
+ * @author Greg Turnquist
+ */
+public interface LinkDiscovererStandardUnitTest {
+
+ String RELATION = "http://www.foo.com/bar";
+
+ LinkRelation LINK_RELATION = LinkRelation.of(RELATION);
+
+ /**
+ * Media type provider must provider an instance of their {@link LinkDiscoverer}.
+ */
+ LinkDiscoverer getLinkDiscoverer();
+
+ /**
+ * Media type provider must provide a JSON-based collection of links.
+ */
+ default String getInputString() {
+
+ try {
+ return read(new ClassPathResource("standard-link-discoverer-unit-test.json", getClass()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ default void findLinkWithRelByString() {
+
+ Optional optionalLink = getLinkDiscoverer().findLinkWithRel(RELATION, getInputString());
+
+ assertThat(optionalLink).isNotEmpty();
+ assertLink(optionalLink.orElseThrow(RuntimeException::new));
+ }
+
+ @Test
+ default void findLinkWithRelByLinkRelation() {
+
+ Optional optionalLink = getLinkDiscoverer().findLinkWithRel(LINK_RELATION, getInputString());
+
+ assertThat(optionalLink).isNotEmpty();
+ assertLink(optionalLink.orElseThrow(RuntimeException::new));
+ }
+
+ @Test
+ default void findRequiredLinkWithRelByLinkRelation() {
+
+ Link link = getLinkDiscoverer().findRequiredLinkWithRel(LINK_RELATION, getInputString());
+
+ assertLink(link);
+ }
+
+ @Test
+ default void findLinkWithRelByLinkRelationAndInputStream() {
+
+ Optional optionalLink = getLinkDiscoverer().findLinkWithRel(LINK_RELATION,
+ new ByteArrayInputStream(getInputString().getBytes()));
+
+ assertThat(optionalLink).isNotEmpty();
+ assertLink(optionalLink.orElseThrow(RuntimeException::new));
+ }
+
+ @Test
+ default void findLinkWithRelByStringAndInputStream() {
+
+ Optional optionalLink = getLinkDiscoverer().findLinkWithRel(RELATION,
+ new ByteArrayInputStream(getInputString().getBytes()));
+
+ assertThat(optionalLink).isNotEmpty();
+ assertLink(optionalLink.orElseThrow(RuntimeException::new));
+ }
+
+ @Test
+ default void findRequiredLinkWithRelByLinkRelationAndInputStream() {
+
+ Link link = getLinkDiscoverer().findRequiredLinkWithRel(LINK_RELATION,
+ new ByteArrayInputStream(getInputString().getBytes()));
+
+ assertLink(link);
+ }
+
+ @Test
+ default void findLinksWithRelByString() {
+
+ Links links = getLinkDiscoverer().findLinksWithRel(RELATION, getInputString());
+
+ assertLinks(links);
+ }
+
+ @Test
+ default void findLinksWithRelByLinkRelation() {
+
+ Links links = getLinkDiscoverer().findLinksWithRel(LINK_RELATION, getInputString());
+
+ assertLinks(links);
+ }
+
+ @Test
+ default void findLinksWithRelByStringAndInputStream() {
+
+ Links links = getLinkDiscoverer().findLinksWithRel(RELATION, new ByteArrayInputStream(getInputString().getBytes()));
+
+ assertLinks(links);
+ }
+
+ @Test
+ default void findLinksWithRelByLinkRelationAndInputStream() {
+
+ Links links = getLinkDiscoverer().findLinksWithRel(LINK_RELATION, new ByteArrayInputStream(getInputString().getBytes()));
+
+ assertLinks(links);
+ }
+
+ /**
+ * Verify the details of a standard set of {@link Link}s.
+ *
+ * @param link
+ */
+ static void assertLink(Link link) {
+
+ assertThat(link.getRel()).isEqualTo(LINK_RELATION);
+ assertThat(link.getHref()).isEqualTo("https://www.foo.com/bar/whatever");
+ }
+
+ /**
+ * Verify the details of a standard combined set of {@link Links}.
+ *
+ * @param links
+ */
+ static void assertLinks(Links links) {
+
+ assertThat(links).hasSize(1);
+ assertThat(links).extracting(Link::getRel).containsExactly(LINK_RELATION);
+ assertThat(links).extracting(Link::getHref).containsExactly("https://www.foo.com/bar/whatever");
+ }
+
+}
diff --git a/src/test/java/org/springframework/hateoas/mediatype/collectionjson/CollectionJsonLinkDiscovererStandardUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/collectionjson/CollectionJsonLinkDiscovererStandardUnitTest.java
new file mode 100644
index 00000000..6df41e1c
--- /dev/null
+++ b/src/test/java/org/springframework/hateoas/mediatype/collectionjson/CollectionJsonLinkDiscovererStandardUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.hateoas.mediatype.collectionjson;
+
+import org.springframework.hateoas.client.LinkDiscoverer;
+import org.springframework.hateoas.mediatype.LinkDiscovererStandardUnitTest;
+
+/**
+ * @author Greg Turnquist
+ */
+public class CollectionJsonLinkDiscovererStandardUnitTest implements LinkDiscovererStandardUnitTest {
+
+ static final LinkDiscoverer discoverer = new CollectionJsonLinkDiscoverer();
+
+ @Override
+ public LinkDiscoverer getLinkDiscoverer() {
+ return discoverer;
+ }
+}
diff --git a/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererStandardUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererStandardUnitTest.java
new file mode 100644
index 00000000..1e8ba693
--- /dev/null
+++ b/src/test/java/org/springframework/hateoas/mediatype/hal/HalLinkDiscovererStandardUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.hateoas.mediatype.hal;
+
+import org.springframework.hateoas.client.LinkDiscoverer;
+import org.springframework.hateoas.mediatype.LinkDiscovererStandardUnitTest;
+
+/**
+ * @author Greg Turnquist
+ */
+public class HalLinkDiscovererStandardUnitTest implements LinkDiscovererStandardUnitTest {
+
+ static final LinkDiscoverer discoverer = new HalLinkDiscoverer();
+
+ @Override
+ public LinkDiscoverer getLinkDiscoverer() {
+ return discoverer;
+ }
+}
diff --git a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererStandardUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererStandardUnitTest.java
new file mode 100644
index 00000000..b4e05e76
--- /dev/null
+++ b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscovererStandardUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.hateoas.mediatype.hal.forms;
+
+import org.springframework.hateoas.client.LinkDiscoverer;
+import org.springframework.hateoas.mediatype.LinkDiscovererStandardUnitTest;
+
+/**
+ * @author Greg Turnquist
+ */
+public class HalFormsLinkDiscovererStandardUnitTest implements LinkDiscovererStandardUnitTest {
+
+ static final LinkDiscoverer discoverer = new HalFormsLinkDiscoverer();
+
+ @Override
+ public LinkDiscoverer getLinkDiscoverer() {
+ return discoverer;
+ }
+}
diff --git a/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererStandardUnitTest.java b/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererStandardUnitTest.java
new file mode 100644
index 00000000..fbc39870
--- /dev/null
+++ b/src/test/java/org/springframework/hateoas/mediatype/uber/UberLinkDiscovererStandardUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.hateoas.mediatype.uber;
+
+import org.springframework.hateoas.client.LinkDiscoverer;
+import org.springframework.hateoas.mediatype.LinkDiscovererStandardUnitTest;
+
+/**
+ * @author Greg Turnquist
+ */
+public class UberLinkDiscovererStandardUnitTest implements LinkDiscovererStandardUnitTest {
+
+ static final LinkDiscoverer discoverer = new UberLinkDiscoverer();
+
+ @Override
+ public LinkDiscoverer getLinkDiscoverer() {
+ return discoverer;
+ }
+}
diff --git a/src/test/resources/org/springframework/hateoas/mediatype/collectionjson/standard-link-discoverer-unit-test.json b/src/test/resources/org/springframework/hateoas/mediatype/collectionjson/standard-link-discoverer-unit-test.json
new file mode 100644
index 00000000..f96e3850
--- /dev/null
+++ b/src/test/resources/org/springframework/hateoas/mediatype/collectionjson/standard-link-discoverer-unit-test.json
@@ -0,0 +1,13 @@
+{
+ "collection" :
+ {
+ "version" : "1.0",
+ "href" : "http://example.com",
+ "links" : [
+ {
+ "rel": "http://www.foo.com/bar",
+ "href": "https://www.foo.com/bar/whatever"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/org/springframework/hateoas/mediatype/hal/forms/standard-link-discoverer-unit-test.json b/src/test/resources/org/springframework/hateoas/mediatype/hal/forms/standard-link-discoverer-unit-test.json
new file mode 100644
index 00000000..eeeec6d2
--- /dev/null
+++ b/src/test/resources/org/springframework/hateoas/mediatype/hal/forms/standard-link-discoverer-unit-test.json
@@ -0,0 +1,18 @@
+{
+ "_links": {
+ "self": {
+ "href": "selfHref"
+ },
+ "relation": [
+ {
+ "href": "firstHref"
+ },
+ {
+ "href": "secondHref"
+ }
+ ],
+ "http://www.foo.com/bar": {
+ "href": "https://www.foo.com/bar/whatever"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/org/springframework/hateoas/mediatype/hal/standard-link-discoverer-unit-test.json b/src/test/resources/org/springframework/hateoas/mediatype/hal/standard-link-discoverer-unit-test.json
new file mode 100644
index 00000000..eeeec6d2
--- /dev/null
+++ b/src/test/resources/org/springframework/hateoas/mediatype/hal/standard-link-discoverer-unit-test.json
@@ -0,0 +1,18 @@
+{
+ "_links": {
+ "self": {
+ "href": "selfHref"
+ },
+ "relation": [
+ {
+ "href": "firstHref"
+ },
+ {
+ "href": "secondHref"
+ }
+ ],
+ "http://www.foo.com/bar": {
+ "href": "https://www.foo.com/bar/whatever"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/org/springframework/hateoas/mediatype/uber/standard-link-discoverer-unit-test.json b/src/test/resources/org/springframework/hateoas/mediatype/uber/standard-link-discoverer-unit-test.json
new file mode 100644
index 00000000..6a3501e8
--- /dev/null
+++ b/src/test/resources/org/springframework/hateoas/mediatype/uber/standard-link-discoverer-unit-test.json
@@ -0,0 +1,25 @@
+{
+ "uber" :
+ {
+ "version" : "1.0",
+ "data" :
+ [
+ {
+ "rel" : ["self"],
+ "url" : "selfHref"
+ },
+ {
+ "rel" : ["relation"],
+ "url" : "firstHref"
+ },
+ {
+ "rel" : ["relation"],
+ "url" : "secondHref"
+ },
+ {
+ "rel" : ["http://www.foo.com/bar"],
+ "url" : "https://www.foo.com/bar/whatever"
+ }
+ ]
+ }
+}
\ No newline at end of file