EffectStep
An EffectStep
can be understood as the following function ScenarioContext => Future[Either[CornichonError, Session]]
.
This means that an EffectStep
runs a side effect and populates the Session
with potential result values or returns an error.
A Session
is a Map-like object used to propagate state throughout a scenario
. It is used to resolve placeholders and save the result computations for later assertions.
Here is the simplest EffectStep
possible:
When I EffectStep(title = "do nothing", action = scenarioContext => Future.successful(Right(scenarioContext.session)))
or using a factory helper when dealing with computations that do not fit the EffectStep
type.
When I EffectStep.fromSync(title = "do nothing", action = scenarioContext => scenarioContext.session)
When I EffectStep.fromSyncE(title = "do nothing", action = scenarioContext => Right(scenarioContext.session))
When I EffectStep.fromAsync(title = "do nothing", action = scenarioContext => Future(scenarioContext.session))
Let’s try to save a value into the Session
When I EffectStep.fromSync(title = "estimate PI", action = scenarioContext => scenarioContext.session.add("result", piComputation()))
The test engine is responsible for controlling the execution of the side effect function and to report any error.
If you prefer not using the scala.concurrent.Future
as effect, it is possible to use the Effect
type from cats-effect
.
import com.github.agourlay.cornichon.steps.cats.EffectStep
val myTaskEffect = EffectStep("identity task", scenarioContext => Task.now(Right(scenarioContext.session)))
EffectStep using the HTTP service
Sometimes you want to perform HTTP calls inside an EffectStep
, this is where the httpService
comes in handy.
In order to illustrate its usage let’s take the following example, you would like to write a custom step like:
def feature = Feature("Customer endpoint") {
Scenario("create customer") {
When I create_customer
Then assert status.is(201)
}
}
Most of the time you will create your own trait containing your custom steps and declare a self-type on CornichonFeature
to be able to access the httpService
.
It exposes a method requestEffect
turning an HttpRequest
into an asynchronous effect.
trait MySteps {
this: CornichonFeature ⇒
def create_customer = EffectStep(
title = "create new customer",
effect = http.requestEffect(
request = HttpRequest.post("/customer").withPayload("someJson"),
expectedStatus = Some(201)
extractor = RootExtractor("customer")
)
)
}
The built-in HTTP steps available on the DSL are actually built on top of the httpService
which means that you benefit from all the existing infrastructure to:
- resolve placeholders in URL, query params, body and headers.
- automatically populate the session with the results of the call such as response body, status and headers (it is also possible to pass a custom extractor).
- handle common errors such as timeout and malformed requests.