package object resolution in main and test scopes

383 views
Skip to first unread message

Charles vinodh

unread,
Mar 22, 2016, 11:06:33 PM3/22/16
to scala-user
I have a package object defined in both the main and the test code tree as shown below.  in run scope the package object in main/ takes effect and in test scope the package object under test/ takes effect. For eg

src/main/scala/com/example/testbed/package.scala
package object testbed {
  val foo = "bar"
}
src/test/scala/com/example/testbed/package.scala
package object testbed {
  val foo = "baz"
}
src/main/scala/com/example/testbed/Main.scala
object Main extends App {
  println(Run.run)
}

object Run {
  def run = foo
}
src/test/scala/com/example/testbed/TestSpec.scala
class TestSpec extends FlatSpec with MustMatchers {
  "Package Object" must "return baz" in {
    Run.run must equal ("baz")
  }
}
on run scope the value the output is "bar" as expected and on test scope the test cases succeed since com.example.testbed.foo value is "baz"

Is this just a quirk of SBT or is it a well defined sbt trait?. I currently use this behaviour for dependency injection by defining my module bindings for production and test in their corresponding package objects. This is an advisable approach? and if not why?

Oliver Ruebenacker

unread,
Mar 23, 2016, 11:19:08 AM3/23/16
to Charles vinodh, scala-user

     Hello,

  I would not advice.

  When you run in normal mode, testbed in test is not included. When you run in test mode, both testbed objects are included and the one that comes first on the class path wins.

  In this case, you might compile some code against testbed in main, and then the code runs with testbed in test, and if you call a method in testbed in main, and the testbed in test does not have that method, or it does not have the same signature, you get a runtime exception.

  Having two objects of the same name is also likely to confuse tools and developers.

     Best, Oliver

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

Charles vinodh

unread,
Mar 23, 2016, 10:23:20 PM3/23/16
to Oliver Ruebenacker, scala-user
  In this case, you might compile some code against testbed in main, and then the code runs with testbed in test, and if you call a method in testbed in main, and the testbed in test does not have that method, or it does not have the same signature, you get a runtime exception.

Yeah I agree. but basically aren't we deferring these failures from compile-time to test-time but not run-time?. 


  Having two objects of the same name is also likely to confuse tools and developers. 

Yeah, this is true. On the other hand the advantages I see is that, with zero boilerplate we have changed the output of Run.run in test scope. It will be nice to have something similar as a language feature :) .

Oliver Ruebenacker

unread,
Mar 24, 2016, 9:09:58 AM3/24/16
to Charles vinodh, scala-user

     Hello,

  I meant run time as opposed to compile time, so test time is just another run time.

  Why not just have the test itself set things up the way you want it for testing?

     Best, Oliver

Charles vinodh

unread,
Mar 24, 2016, 10:10:33 PM3/24/16
to scala-user, mig.f...@gmail.com
Thanks Oliver!!

I was just seeing what is the consensus on this approach. my major worry was if this behaviour was not guaranteed then it might stop working in any future version of scala/jvm.
Reply all
Reply to author
Forward
0 new messages