문제

The scenario:

import org.scalatest.{ BeforeAndAfterAll, FeatureSpec, GivenWhenThen, Matchers }
import org.scalatest.concurrent.{ ScalaFutures, Futures }
import org.scalatest.time.{ Millis, Seconds, Span }

trait UniqueUserSpec extends FeatureSpec with GivenWhenThen with BeforeAndAfterAll with ScalaFutures {
  implicit override val patienceConfig =
    PatienceConfig(timeout = Span(5, Seconds), interval = Span(5, Millis))
  var user: Users = _
  override def beforeAll: Unit = {
    this.synchronized {
      user = TestHelper.createAndRegisterAUser()
    }
  }
}

In the TestHelper.createAndRegisterAUser() method, all actions are blocking and synchronous, from creation to DB writing etc.

Now:

class SomeActualTests extends UniqueUserSpec {
   feature("Something is possible") {
     scenario("some conditions") {
       Given("an api call is made to etc..")
       val req = url(API_END_POINT) / "route" <<? Map("test", "test")
       whenReady(req.POST) {
         response => {
           Then("The response status should be 200")
           response.getStatusCode shouldEqual 200
         }
       }
     }
   }
}

The problem: The behaviour of beforeAll is unreliable, several tests failing because it didn't execute before all tests.

If I create a separate user inside every scenario, things work. If I try to use the one beforeAll was supposed to create, the object hasn't been written to DB.

What am I doing wrong concurrency wise, if anything?

Is there a better way to do something "before all tests" in a Feature?

도움이 되었습니까?

해결책

Are you trying to create a user before each test, such that each test gets its own user? If so you want BeforeAndAfterEach instead. BeforeAndAfterAll happens once for the whole suite, before any tests have happened. Then all tests can share the same user.

If BeforeAndAfterAll is indeed what you want, then my next question would be is createAndRegisterAUser actually finished by the time the method returns? If not, then that's likely where your race conditions lies.

If that's not it, then I'd ask have you synchronized access to the user var from your tests? If not, and those tests are run in different threads, Java's memory model does not guarantee that the reading threads will actually see the write done by beforeAll. The usual way, though, that you would have tests running in different threads is to use ParallelTestExecution, and I don't see you using that here. If you did use that, then it would create an instance of the test class for each test (ParallelTestExecution extends OneInstancePerTest), and that would solve your synchronization problem. So most likely that's not it either.

If solving this requires some more back and forth, it might be easier to figure it out on scalatest-users.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top