Testing with Hoverfly and Java Part 3: State

Previously we simulated a delay scenario using Hoverfly. Now it’s time to dive deeper and go for a state based testing. By doing a stateful simulation we can change the way the tests endpoints behave based on how the state changed.

 

Hoverfly does have a state capability. State in a hoverfly simulation is like a map. Initially it is empty but you can define how it will get populated per request.

Our strategy would be to have a request that initializes the state and then specifies other requests that change that state.

public class SimulationStateTests {

	private Hoverfly hoverfly;

	@BeforeEach
	void setUp() {
		var simulation = SimulationSource.dsl(service("http://localhost:8085")
				.get("/initialize")
				.willReturn(success("{\"initialized\":true}", "application/json")
						.andSetState("shouldSucceed", "true")
				)
				.get("/state")
				.withState("shouldSucceed", "false")
				.willReturn(serverError().andSetState("shouldSucceed", "true"))
				.get("/state")
				.withState("shouldSucceed", "true")
				.willReturn(success("{\"username\":\"test-user\"}", "application/json")
						.andSetState("shouldSucceed", "false"))

		);

		var localConfig = HoverflyConfig.localConfigs().disableTlsVerification().asWebServer().proxyPort(8085);
		hoverfly = new Hoverfly(localConfig, SIMULATE);
		hoverfly.start();
		hoverfly.simulate(simulation);
	}

	@AfterEach
	void tearDown() {
		hoverfly.close();
	}

}

Unfortunately on the state we can only specify values in a key value fashion and not by passing a function for a key.
However with the right workaround many scenarios could be simulated.

In the example we first initialize the state and the we issue requests that behave differently based on the state, but also they do change the state.

So we expect to have a continuous first succeed and then fail mode, which can be depicted in the following test.

	@Test
	void testWithState() {
		var client = HttpClient.newHttpClient();
		var initializationRequest = HttpRequest.newBuilder()
				.uri(URI.create("http://localhost:8085/initialize"))
				.build();
		var initializationResponse = client.sendAsync(initializationRequest, HttpResponse.BodyHandlers.ofString())
				.thenApply(HttpResponse::body)
				.join();
		Assertions.assertEquals("{\"initialized\":true}", initializationResponse);

		var statefulRequest = HttpRequest.newBuilder()
				.uri(URI.create("http://localhost:8085/state"))
				.build();

		for (int i = 0; i < 100; i++) {
			var response = client.sendAsync(statefulRequest, HttpResponse.BodyHandlers.ofString())
					.join();

			int statusCode = i % 2 == 0 ? 200 : 500;

			Assertions.assertEquals(statusCode, response.statusCode());
		}
	}

That’s all about stateful simulation. On the next part we shall proceed on Hoverfly matchers