I am playing with ZIO and built a simple application that get content via HTTP :
for {
options <- Options.parse(args)
http = HttpClient(args)
content <- Download.execute(args.resource).provide(http)
} yield ()
It does the job but the client is backed by Play StandaloneWsClient and I would like to close it and terminate the actor system as described in the documentation: https://github.com/playframework/play-ws#scala-1
So I created a finaliser method but it seems that is has no effect:
// ...
content <- Download.execute(args.resource).ensuring(http.disconnect()).provide(http)
// ...
class HttpClient {
// ...
def disconnect():UIO[Unit] = ZIO.effectTotal {
client.close()
system.terminate()
}
How can I instruct ZIO to call a finaliser method to free up my resources ?
I've got pretty simple application that uses Jooby as web framework. Its class responsible for REST looks like this
class Sandbox : Kooby ({
path("/sandbox") {
get {
val environment = require(Config::class).getString("application.env")
"Current environment: $environment"
}
get ("/:name") {
val name = param("name")
"Auto response $name"
}
}
})
I want to write integration test for it. My test looks like this. I use spock and rest-assured. The thing is that I don't have the application running and want to run it using some kind of embedded server or whatever. How to do that?
My simple test looks like this
class SandboxTest extends Specification {
def "check current environment"() {
given:
def request = given()
when:
def response = request.when().get("/sandbox")
then:
response.then().statusCode(200) // for now 404
}
}
You need to look for before/after test (or class) hooks in Spock. In the before hook you start Jooby without blocking the thread:
app.start("server.join=false")
in the after hook:
app.stop();
Never used Spock but here is a small extension method for Spek:
fun SpecBody.jooby(app: Jooby, body: SpecBody.() -> Unit) {
beforeGroup {
app.start("server.join=false")
}
body()
afterGroup {
app.stop()
}
}
Finally from your test:
#RunWith(JUnitPlatform::class)
object AppTest : Spek({
jooby(App()) {
describe("Get with query parameter") {
given("queryParameter name=Kotlin") {
it("should return Hello Kotlin!") {
val name = "Kotlin"
given()
.queryParam("name", name)
.`when`()
.get("/")
.then()
.assertThat()
.statusCode(Status.OK.value())
.extract()
.asString()
.let {
assertEquals(it, "Hello $name!")
}
}
...
...
...
...
Maven Spek example
Gradle Spek example
This drives me crazy, I have 2 http requests in a sample application:
open class RestController : Controller() {
val api = Rest()
init {
api.baseURI = "http://127.0.0.1:5059/"
}
}
class PendingCtlr : RestController() {
fun load(): ObservableList<PendingEntity> {
val txt = api.get("pendings").list()
val temp = txt.toModel<PendingEntity>()
return temp.observable()
}
}
class ConfirmedCtrl : RestController() {
fun load(id: Long): ObservableList<ConfirmedEntity> {
val li= api.get("confirmeds").list()
val temp = li.toModel<ConfirmedEntity>()
return temp.observable()
}
}
The first one works, the second one doesn't even hit the application level, it gets rejected with 400 BadRequest by my backend (Werkzeug).
I see absolutely no difference in both functions, and I can call both routes from my Swagger, as well as from python as well as from curl! Could someone please advise at least where to look for debug?
EDIT: The problem was on server side -_- Solved
Here is my simple routing application:
object Main extends App with SimpleRoutingApp {
implicit val system = ActorSystem("my-system")
startServer(interface = "0.0.0.0", port = System.getenv("PORT").toInt) {
import format.UsageJsonFormat._
import spray.httpx.SprayJsonSupport._
path("") {
get {
complete("OK")
}
} ~
path("meter" / JavaUUID) {
meterUUID => pathEnd {
post {
entity(as[Usage]) {
usage =>
// execute some logic asynchronously
// do not wait for the result
complete("OK")
}
}
}
}
}
}
What I want to achieve is to execute some logic asynchronously in my path directive, do not wait for the result and return immediately HTTP 200 OK.
I am quite new to Scala and spray and wondering if there is any spray way to solve this specific problem. Otherwise I would go into direction of creating Actor for every request and letting it to do the job. Please advice.
There's no special way of handling this in spray: simply fire your async action (a method returning a Future, a message sent to an actor, whatever) and call complete right after.
def doStuffAsync = Future {
// literally anything
}
path("meter" / JavaUUID) { meterUUID =>
pathEnd {
post {
entity(as[Usage]) { usage =>
doStuffAsync()
complete("OK")
}
}
}
}
Conversely, if you need to wait for an async action to complete before sending the response, you can use spray-specific directives for working with Futures or Actors.
I'd like to test a Grails controller that is sending out emails using the grails Email plugin. I'm at a loss exactly how to mock the sendMail closure in order for interactions to work. Here's my latest version of the test code:
def 'controller should send a multipart email'() {
given: 'a mocked mailService'
controller.mailService = Mock(grails.plugin.mail.MailService)
controller.mailService.sendMail(*_) >> Mock(org.springframework.mail.MailMessage)
when:
controller.sendNow()
then:
1* _.multipart(true)
}
The controller code looks something like what you'd expect, e.g.:
def mailService
def sendNow() {
mailService.sendMail {
multipart true
to 'example#example.org'
from 'me#here.com'
subject 'a subject'
body 'a body'
}
}
If I run this test, I get 0 invocations of my multipart interaction instead of 1. The second line of the given: block seems suspicious to me, but if I try to mock a Closure instead of org.springframework.mail.MailMessage my test crashes. I should also mention that the controller itself works as expected (it couldn't wait for me to figure out the unit tests first).
Edited
Aha, looking at the code with a fresh mind a few hours later, I can see why the above code does not work; in order for me to catch multipart and other DSL calls, I would have to mock the closure itself, not the sendMail method (and I can't do that since the closure is defined inside the controller itself). What I probably can do is check the arguments to the sendMail method to see everything necessary was passed into it.
I was able to achieve this in Spock with the following:
def messageBuilder
def bodyParams
def setup(){
def mockMailService = new MockFor(MailService)
mockMailService.ignore.sendMail{ callable ->
messageBuilder = new MailMessageBuilder(null, new ConfigObject())
messageBuilder.metaClass.body = { Map params ->
bodyParams = params
}
callable.delegate = messageBuilder
callable.resolveStrategy = Closure.DELEGATE_FIRST
callable.call()
}
service.mailService = mockMailService.proxyInstance()
}
And an example test:
def "sendEmailReceipt_passesCorrectParams"(){
when:
def receiptItems = [] << [item: "item1", price: 100]
service.sendEmailReceipt(receiptItems, "some#email.com")
then:
messageBuilder.message.to[0] == "some#email.com"
messageBuilder.message.subject == "My subject"
bodyParams.view == "/mailtemplates/emailReceipt"
bodyParams.model.receiptItems == data
}
You can install the greenMail plugin, and use it in an integration test:
From the greenmail plugin home page:
import com.icegreen.greenmail.util.*
class GreenmailTests extends GroovyTestCase {
def mailService
def greenMail
void testSendMail() {
Map mail = [message:'hello world', from:'from#piragua.com', to:'to#piragua.com', subject:'subject']
mailService.sendMail {
to mail.to
from mail.from
subject mail.subject
body mail.message
}
assertEquals(1, greenMail.getReceivedMessages().length)
def message = greenMail.getReceivedMessages()[0]
assertEquals(mail.message, GreenMailUtil.getBody(message))
assertEquals(mail.from, GreenMailUtil.getAddressList(message.from))
assertEquals(mail.subject, message.subject)
}
void tearDown() {
greenMail.deleteAllMessages()
}
}
I'm not a Spock expert but you should be able to translate this junit test to spock style.
Source: http://grails.org/plugin/greenmail
Udpate, alternative by mocking sendMail
This is an answer to Gregor's update. In my opinion, you would have to mock the sendMail method, and inside this method have an stub that implements the different properties and methods that are used in the closure. Lets call it an evaluator. The you would initialize the closure's delegate to the evaluatro, and execute the closure. The evaluator should have the assertions. You see that I'm using more junit concepts here. I don't know how easily you can translate that into spock concepts. You probably would be able to us the behaviour checking facilities of spock.
class MailVerifier {
void multiPart(boolean v){
//...
}
void to(String address){
//...
}
boolean isVerified() {
//check internal state obtained by the appropriate invocation of the methods
}
}
def sendMail(Closure mailDefintion) {
def evaluator = createMailVerifier()
mailDefinition.delegate = evaluator
mailDefinition()
assert evaluator.verified
}
Take a look at plugin tests here: plugin integration test and here: plugin unit test. In my opinion it would be hard for you to mock all MailService dependencies - factory and builder that builds your mail message. I'd end up with testing only if my controller's sendNow is called.
Edit
I've found this answer. According to it you can try:
def 'controller should send a multipart email'() {
given: 'a mocked mailService'
def mockMailService = new Object()
def mockMessageBuilder = Mock(MessageBuilder)
mockMailService.metaClass.sendMail = { callable ->
callable.delegate = mockMessageBuilder
callable.resolveStrategy = Closure.DELEGATE_FIRST
callable.call()
}
controller.mailService = mockMailService
when:
controller.sendNow()
then:
1* mockMessageBuilder.multipart(true)
}
def mailService = Mock(MailService)
mockMailService.metaClass.sendMail = { ... your logic ... }
controller.mailService = mailService