Reputation: 1044
I'm having some trouble figuring out the best way create an easy way to test some of my DB centric application code. Maybe I am skewed from more OO languages, but what I am trying to do is start the application, seed the database, pass seeded data to the test, then clean up the database. I was trying to use before and after blocks, but have been running into all sorts of problem with delayedInit and other race conditions. In the docs you can use the setupData and deleteData, but it doesn't provide an opportunity to pass data to the actual tests. Is there any way this could be achieved?
Here is a sample of the wrapper I am using:
abstract class WithUserData extends WithApplication {
var user = null
override def around[T: AsResult](t: => T): Result = super.around {
setupData()
t
deleteData()
}
def setupData() {
Logger.info("Running Before")
val passwordInfo = PasswordInfo("bcrypt", "$2a$10$at8N/GZHKDbHLh6er.UsbOUjVqx.IGebO2Wc7EmmD2m4tOlin7EAG")
val u = User(new IdentityId("[email protected]", UsernamePasswordProvider.UsernamePassword), "Harry",
"Potter", "Harry Potter", Option("[email protected]"), None, AuthenticationMethod.UserPassword,
None, None, Some(passwordInfo), None, None, "", Subscription.free, None, None, None, List(), None)
User.save(u)
Logger.info(s"Before User is before saving : var ${user} --- variable ${u}")
user = u
Logger.info(s"variable user is ${user}")
}
def deleteData(): Unit ={
Logger.info(s"After User is -> $user")
Logger.info("Removing the user")
User.remove(user)
}
}
Then in my test, I would love to use it like this:
"with wrong password will not allow user to be logged in" in new WithUserData{
Logger.info(s"Running test 1 with User ${user}")
val fakeRequest = FakeRequest(POST, "/authenticate/userpass", FakeHeaders(), "").withFormUrlEncodedBody(("email" , user.email.get), ("password", "Blah"))
val request = route(fakeRequest).get
status(request) must equalTo(BAD_REQUEST)
}
The code above won't work and will give odd errors about user being null, even though the before is being run first. Is there any way for me to pass around a saved user object? I would love to not have to query the object every test. It seems like a lot of boiler plate and should be something handled in before and after.
Any help would be greatly appreciated!
Thanks,
Mike
Upvotes: 3
Views: 335
Reputation: 109
Loock at http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
You can use something like cake pattern
case class User(id: BigInt, name: String)
trait UserRepositoryComponent {
def userLocator: UserLocator
trait UserLocator {
def getUser: User
def removeUser(user: User)
}
}
trait UserTestRepositoryComponent extends UserRepositoryComponent {
def userLocator = new UserTestLocator
class UserTestLocator extends UserLocator {
override def getUser: User = User(1, "test user")
override def removeUser(user: User): Unit = ()
}
}
trait UserRealRepositoryComponent extends UserRepositoryComponent {
def userLocator = new UserRealLocator
class UserRealLocator extends UserLocator {
override def getUser: User = User(1, "real user")
override def removeUser(user: User): Unit = ()
}
}
trait UserServiceComponent {
this: UserRepositoryComponent =>
def getUser: User = userLocator.getUser
def removeUser(user: User) = userLocator.removeUser(user)
}
trait WithUserData {
this: UserServiceComponent =>
println(getUser)
}
object Main extends App {
val userDataFake: WithUserData = new WithUserData with UserServiceComponent with UserTestRepositoryComponent
val userDataReal: WithUserData = new WithUserData with UserServiceComponent with UserRealRepositoryComponent
}
Or somthing like http://docs.scala-lang.org/tutorials/tour/implicit-parameters.html
Upvotes: 1