英文:
Scalatra asyncPost multiple unit tests mixed up requests
问题
I'm new to Scala, so I may not be clear about the issue I'm facing, and I may not have included all the necessary details to identify the problem. I'll do my best to clarify.
I'm converting a post
endpoint in Scalatra to an asyncPost
endpoint and changing Await.result
calls to use Future
s. The unit tests that used to pass are now failing intermittently, with one test being executed with the request from another test. When I remove all tests and run each test individually, they all pass. At this point, my hypothesis is that the requests are getting mixed up across unit tests. I'm unsure if this is an issue with the code or the unit test setup.
This is production code, so there's a lot of logic that I can't include here, but I'll try to keep what I think is relevant.
Actual code:
class Endpoints(...)
extends ...
with ABC_ExecutionContext
with FutureSupport {
protected implicit def executor = executionContext
val myEndpoint: Route = asyncPost("/endpoint/", operation(queryGroup)) {
setTransactionName(":post /endpoint")
new AsyncResult { val is = {
for {
...
out <- doSomethingWithRequest() // implicit request is passed, returns a Future
...
response <- doSomething(out) // returns a Future
} yield response
}}
}
}
Tests:
class EndpointsSpec
extends MockitoSugar
with JsonFormats
with ... {
"POST /endpoint on Endpoints" should {
"should work for request A" in {
post("/endpoint/",
write(mockRequestA).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something A"""
status must_== 200
}
}
"should work for request B" in {
post("/endpoint/",
write(mockRequestB).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something B"""
status must_== 200
}
}
}
}
I also tried to create a context per unit test:
class EndpointsSpec
extends MockitoSugar
with JsonFormats
with ... {
"POST /endpoint on Endpoints" should {
"should work for request A" in {
val context: HystrixRequestContext = HystrixRequestContext.initializeContext
try {
post("/endpoint/",
write(mockRequestA).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something A"""
status must_== 200
}
} finally {
context.shutdown()
}
}
"should work for request B" in {
val context: HystrixRequestContext = HystrixRequestContext.initializeContext
try {
post("/endpoint/",
write(mockRequestB).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something B"""
status must_== 200
}
} finally {
context.shutdown()
}
}
}
}
The issue might be related to something I have omitted. Please let me know if you need more details before making the sample code too complex.
Extra info:
- Test framework: specs2 + Mockito
英文:
I'm new to scala so I might not be clear with the issue I'm facing, I might not be including all the details needed to identify the issue. I'll do my best to clarify.
I'm converting a post
scalatra endpoint to asyncPost
and converting Await.result
s to Future
s. The unit tests that used to pass are now failing intermittently: a test is executed with request from another test. When I remove all tests and run each test individually they all pass. At this point my hypothesis is that the requests are being mixed up across unit tests. I'm not sure if this is an issue with the code or unit test setup.
This is a production code so there is a lot of logic that I can't fit here, I try to remove everything and keep what I think is relevant.
Actual code:
class Endpoints(...)
extends ...
with ABC_ExecutionContext
with FutureSupport {
protected implicit def executor = executionContext
val myEndpoint: Route = asyncPost("/endpoint/", operation(queryGroup)) {
setTransactionName(":post /endpoint")
new AsyncResult { val is = {
for {
...
out <- doSomethingWithRequest() // implicit request is passed, returns a Future
...
response <- doSomething(out) // returns a Future
} yield response
}}
}
}
Tests:
class EndpointsSpec
extends MockitoSugar
with JsonFormats
with ... {
"POST /endpoint on Endpoints" should {
"should work for request A" in {
post("/endpoint/",
write(mockRequestA).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something A"""
status must_== 200
}
}
"should work for request B" in {
post("/endpoint/",
write(mockRequestB).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something B"""
status must_== 200
}
}
}
}
I also tried to create a context per unit test
class EndpointsSpec
extends MockitoSugar
with JsonFormats
with ... {
"POST /endpoint on Endpoints" should {
"should work for request A" in {
val context: HystrixRequestContext = HystrixRequestContext.initializeContext
try {
post("/endpoint/",
write(mockRequestA).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something A"""
status must_== 200
}
} finally {
context.shutdown()
}
}
"should work for request B" in {
val context: HystrixRequestContext = HystrixRequestContext.initializeContext
try {
post("/endpoint/",
write(mockRequestB).getBytes(),
Map("user-id" -> "12345")) {
body must_== """something B"""
status must_== 200
}
} finally {
context.shutdown()
}
}
}
}
The issue might be with something I have omitted, let me know and I can add more details before making sample code too complicate
Extra info:
- Test framework: specs2 + mockito
答案1
得分: 1
I don't have experience with Scalatra neither with Specs2. Just giving a quick look to the docs of Scalatra
and how to work with async requests, just using get
, post
or the one you need without the async
prefix should work. From the docs here you have an example:
class MyAppServlet extends ScalatraServlet with FutureSupport {
get("/") {
new AsyncResult { val is =
Future {
// Add async logic here
// ...
}
}
}
}
英文:
I don't have experience with Scalatra neither with Specs2. Just giving a quick look to the docs of Scalatra
and how to work with async requests, just using get
, post
or the one you need without the async
prefxi should work. From the docs here you have an example
class MyAppServlet extends ScalatraServlet with FutureSupport {
get("/"){
new AsyncResult { val is =
Future {
// Add async logic here
// ...
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论