3

I am implementing a file storage service, which is taking a file and saving it into gridFS with special metadata. Of course, I want to be sure everything's working in integration -- files are really stored in database and then retrieved from it.

I use Play Framework 2.1.3 Scala and ReactiveMongo 0.9.

My test cases looks like the following:

"show empty uploaded size on init" in {
  running(FakeApplication()) {
    Await.result(FileStorage.getFilesSize(profileId), duration) must beNone
  }
}

I have tried to wrap every case with running, or all cases, or even Thread.sleep. But database is always up after test fails.

[error] There is no started application
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:51)
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:51)
[error] play.api.Play$.current(Play.scala:51)
[error] content.FileStorage$.db$lzycompute(FileStorage.scala:32)

...

[info] Total for specification FileStorageSpec
[info] Finished in 21 ms
[info] 5 examples, 1 failure, 4 errors
[info] 
[info] application - ReactiveMongoPlugin starting...
[info] application - ReactiveMongoPlugin successfully started with db 'test'! Servers:
        [localhost:27017]
[info] play - Starting application default Akka system.
[info] play - Shutdown application default Akka system.

What am I doing wrong? How do you test ReactiveMongo applications?

Dmitry Kurinskiy
  • 533
  • 1
  • 3
  • 16

1 Answers1

2

In the FileStorage object you have these lines:

lazy val db = ReactiveMongoPlugin.db

val gridFS = GridFS(db, "file")
val collection = db.collection[JSONCollection]("file.files")

collection.indexesManager.ensure(Index(Seq("metadata.profileId" -> IndexType.Ascending)))

When the object is instantiated, the above lines of code are executed. Since you have no control of object instantiation you can not be sure when that happens.

It will probably help to change the lines into this:

def db = ReactiveMongoPlugin.db

def gridFS = GridFS(db, "file")
def collection = {
  val collection = db.collection[JSONCollection]("file.files")
  collection.indexesManager.ensure(Index(Seq("metadata.profileId" -> IndexType.Ascending)))
  collection
}
EECOLOR
  • 11,184
  • 3
  • 41
  • 75
  • It doesn't help :( [info] File Storage should [error] ! show empty uploaded size on init [error] RuntimeException: There is no started application (package.scala:27) [error] play.api.Play$$anonfun$current$1.apply(Play.scala:51) [error] play.api.Play$$anonfun$current$1.apply(Play.scala:51) [error] play.api.Play$.current(Play.scala:51) [error] content.FileStorage$.db$lzycompute(FileStorage.scala:36) [error] content.FileStorage$.db(FileStorage.scala:36) [error] content.FileStorage$.getFilesSize(FileStorage.scala:71) – Dmitry Kurinskiy Sep 17 '13 at 11:41
  • It looks like test case is running before an application is initialized. FileStorage says that there's no started application when tests are launched, hence plugins are not ready and DB object is unreachable. It looks like "running(FakeApplication())" calls app init in one thread, but performs test in another one. – Dmitry Kurinskiy Sep 17 '13 at 11:47
  • Could you post the source of your `FileStorage` object again? – EECOLOR Sep 17 '13 at 14:37
  • it looks like I'm not alone: https://github.com/ReactiveMongo/Play-ReactiveMongo/issues/32#issuecomment-24604964 – Dmitry Kurinskiy Sep 17 '13 at 17:08
  • I've copy-pasted it there: https://gist.github.com/alari/6597372 I think only "val db = ReactiveMongoPlugin.db" matters – Dmitry Kurinskiy Sep 17 '13 at 17:10
  • Instead of `val` for `db`, `gridFS` and `collection` you should use `def`. This allows you to use the code within multiple applications. The other option is to only use one application for all of your tests. You can check the [`ReactiveMongoPlugin`](https://github.com/ReactiveMongo/Play-ReactiveMongo/blob/0.9/src/main/scala/play/modules/reactivemongo/ReactiveMongoPlugin.scala#L21) file to see the relation between the plugin and the current application. – EECOLOR Sep 18 '13 at 06:39