-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #171 from QA-Automation-Starter/159-mockserver-tut…
…orial 159 mockserver tutorial
- Loading branch information
Showing
10 changed files
with
303 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
qa-testing-example/src/main/java/dev/aherscu/qa/testing/example/AbstractMockServerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Copyright 2023 Adrian Herscu | ||
* | ||
* 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 dev.aherscu.qa.testing.example; | ||
|
||
import java.io.*; | ||
import java.net.*; | ||
|
||
import javax.ws.rs.core.*; | ||
|
||
import org.mockserver.client.*; | ||
import org.mockserver.integration.*; | ||
import org.testng.annotations.*; | ||
|
||
import dev.aherscu.qa.jgiven.commons.model.*; | ||
import dev.aherscu.qa.jgiven.commons.steps.*; | ||
import dev.aherscu.qa.jgiven.commons.utils.*; | ||
import dev.aherscu.qa.testing.utils.config.*; | ||
import lombok.*; | ||
import lombok.extern.slf4j.*; | ||
|
||
/** | ||
* Contains REST sample tests just to ensure that the testing infrastructure | ||
* works as required. | ||
* | ||
* @author aherscu | ||
* @param <T> | ||
* type of scenario | ||
* @param <GIVEN> | ||
* type of fixtures | ||
* @param <WHEN> | ||
* type of actions | ||
* @param <THEN> | ||
* type of verifications | ||
* | ||
*/ | ||
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings( | ||
value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", | ||
justification = "JGiven framework limitation") | ||
@Slf4j | ||
abstract public class AbstractMockServerTest<T extends AnyScenarioType, GIVEN extends GenericFixtures<T, ?> & ScenarioType<T>, WHEN extends GenericActions<T, ?> & ScenarioType<T>, THEN extends GenericVerifications<T, ?> & ScenarioType<T>> | ||
extends | ||
UnitilsScenarioTest<BaseConfiguration, T, GIVEN, WHEN, THEN> { | ||
|
||
public static final int DEFAULT_PORT = 1080; | ||
|
||
protected final MockServerClient mockServer; | ||
|
||
private final boolean usingOutOfProcessMockServer; | ||
|
||
/** | ||
* If port 1080 is free will initiate an in-process MockServer, otherwise | ||
* will try connecting to port 1080. | ||
*/ | ||
protected AbstractMockServerTest() { | ||
super(BaseConfiguration.class); | ||
|
||
usingOutOfProcessMockServer = canUseOutOfProcessMockServer(); | ||
|
||
log.debug("using out-of-process MockServer: {}", | ||
usingOutOfProcessMockServer); | ||
|
||
mockServer = usingOutOfProcessMockServer | ||
? new MockServerClient("localhost", outOfProcessPort()) | ||
: ClientAndServer.startClientAndServer(0); | ||
} | ||
|
||
private boolean canUseOutOfProcessMockServer() { | ||
try (val socket = new ServerSocket(outOfProcessPort())) { | ||
socket.close(); | ||
return false; | ||
} catch (final IOException ioe) { | ||
return true; | ||
} | ||
} | ||
|
||
protected int outOfProcessPort() { | ||
return DEFAULT_PORT; | ||
} | ||
|
||
@AfterClass(alwaysRun = true) | ||
protected void stopMockRestServer() { | ||
if (!usingOutOfProcessMockServer) | ||
mockServer.stop(); | ||
} | ||
|
||
protected URI mockServerUri() { | ||
return UriBuilder.fromUri("http://{host}:{port}") | ||
.build("localhost", mockServer.getPort()); | ||
} | ||
} |
179 changes: 179 additions & 0 deletions
179
...st/java/dev/aherscu/qa/testing/example/scenarios/tutorial6/GenericMockServerRestTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/* | ||
* Copyright 2023 Adrian Herscu | ||
* | ||
* 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 dev.aherscu.qa.testing.example.scenarios.tutorial6; | ||
|
||
import static dev.aherscu.qa.testing.utils.StringUtilsExtensions.*; | ||
import static java.util.Arrays.*; | ||
import static javax.ws.rs.core.Response.Status.Family.*; | ||
import static org.hamcrest.Matchers.*; | ||
import static org.mockserver.matchers.Times.*; | ||
import static org.mockserver.model.HttpError.*; | ||
import static org.mockserver.model.HttpRequest.*; | ||
import static org.mockserver.model.HttpResponse.*; | ||
import static org.mockserver.model.MediaType.*; | ||
|
||
import java.util.*; | ||
|
||
import javax.ws.rs.client.*; | ||
|
||
import org.mockserver.mock.*; | ||
import org.mockserver.model.*; | ||
import org.mockserver.verify.*; | ||
import org.testng.annotations.*; | ||
|
||
import dev.aherscu.qa.jgiven.commons.tags.*; | ||
import dev.aherscu.qa.jgiven.rest.model.*; | ||
import dev.aherscu.qa.jgiven.rest.steps.*; | ||
import dev.aherscu.qa.jgiven.rest.tags.*; | ||
import dev.aherscu.qa.testing.example.*; | ||
import dev.aherscu.qa.testing.utils.assertions.*; | ||
import dev.aherscu.qa.testing.utils.rest.*; | ||
import lombok.*; | ||
|
||
/** | ||
* Contains REST sample tests just to ensure that the testing infrastructure | ||
* works as required. | ||
* | ||
* @author aherscu | ||
* | ||
*/ | ||
@SelfTest | ||
@RestTest | ||
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings( | ||
value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", | ||
justification = "JGiven framework limitation") | ||
@SuppressWarnings({ "boxing" }) | ||
public final class GenericMockServerRestTest extends | ||
AbstractMockServerTest<RestScenarioType, RestFixtures<?>, RestActions<?>, RestVerifications<?>> { | ||
|
||
private Client client; | ||
|
||
private Expectation[] expectations; | ||
|
||
private static ExpectationId[] as(final Expectation[] expectations) { | ||
return Arrays.stream(expectations) | ||
.map(Expectation::getId) | ||
.map(ExpectationId::expectationId) | ||
.toArray(ExpectationId[]::new); | ||
} | ||
|
||
@Test | ||
@Reference("159") | ||
@SneakyThrows | ||
public void shouldVerifyAccessByExpectionId() { | ||
given() | ||
.a_REST_client(client); | ||
|
||
when() | ||
.connecting_to(mockServerUri()) | ||
.and().appending_path("dummy") | ||
.and().getting_the_response(); | ||
|
||
then() | ||
.$("the dummy request was sent", | ||
__ -> mockServer.verify(as(expectations))); | ||
} | ||
|
||
@Test | ||
@Reference("159") | ||
@SneakyThrows | ||
public void shouldVerifyAccessByDefinition() { | ||
given() | ||
.a_REST_client(client); | ||
|
||
when() | ||
.connecting_to(mockServerUri()) | ||
.and().appending_path("some-id") | ||
.and().getting_the_response(); | ||
|
||
then() | ||
.the_response_contents(asList( | ||
new JsonAssertion<>("$[0].id", greaterThan(0)), | ||
new JsonAssertion<>("$[1].id", equalTo(2)))) | ||
.and().$("the some id request was sent", | ||
__ -> mockServer.verify(request().withPath("/some-id"))); | ||
} | ||
|
||
@Test | ||
@Reference("159") | ||
@SneakyThrows | ||
public void shouldVerifyAccessedTwice() { | ||
given() | ||
.a_REST_client(client); | ||
|
||
when() | ||
.connecting_to(mockServerUri()) | ||
.and().appending_path("twice") | ||
.and().getting_the_response() | ||
.and().getting_the_response() | ||
.and().getting_the_response(); // should return 404 | ||
|
||
then() | ||
.the_response_status(is(CLIENT_ERROR)) | ||
.and().$("the method was called more than twice", | ||
__ -> mockServer.verify(request().withPath("/twice"), | ||
VerificationTimes.exactly(3))); | ||
} | ||
|
||
@Test | ||
@Reference("159") | ||
@SneakyThrows | ||
public void shouldVerifyAccessOfDroppedConnection() { | ||
given() | ||
.a_REST_client(client); | ||
|
||
when() | ||
.connecting_to(mockServerUri()) | ||
.and().appending_path("drop-connection") | ||
.and().$("trying to access", | ||
self -> self.safely(__ -> self.getting_the_response())); | ||
|
||
then() | ||
.$("the drop connection request was sent", | ||
__ -> mockServer.verify(request() | ||
.withPath("/drop-connection"))); | ||
} | ||
|
||
@AfterClass | ||
private void afterClassCloseRestClient() { | ||
client.close(); | ||
} | ||
|
||
@BeforeClass | ||
private void beforeClassAddExpectations() { | ||
expectations = mockServer // GET is implied | ||
.when(request().withPath("/dummy")) | ||
.respond(response(EMPTY)); | ||
|
||
mockServer // GET is implied | ||
.when(request().withPath("/twice"), exactly(2)) | ||
.respond(response(EMPTY)); | ||
|
||
mockServer // GET is implied | ||
.when(request().withPath("/drop-connection")) | ||
.error(error().withDropConnection(true)); | ||
|
||
mockServer // GET is implied | ||
.when(request().withPath("/some-id")) | ||
.respond(response() | ||
.withBody("[{\"id\":1},{\"id\":2},{\"id\":3}]", JSON_UTF_8)); | ||
} | ||
|
||
@BeforeClass | ||
private void beforeClassOpenRestClient() { | ||
client = LoggingClientBuilder.newClient(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.