I have a Redis PubSub object:
object RedisPubSubService {
implicit val system = ActorSystem("RedisEtatyLib")
val config = ConfigFactory.load.getObject("redis").toConfig
val hostname = config.getString("master")
val port = config.getInt("port")
val client = RedisClient(hostname, port)
val address: InetSocketAddress = new InetSocketAddress(hostname, port)
val channels = Seq("DASHBOARDS")
val patterns = Seq("pattern.*")
var callback: Boolean => Unit = { m => }
val subscriber = system.actorOf(Props(classOf[SubscribeActor], address, channels, patterns, callback)
.withDispatcher("rediscala.rediscala-client-worker-dispatcher")
)
def publish(channel: String, msg: String) =
client.publish(channel, msg)
}
class SubscribeActor(address: InetSocketAddress,
channels: Seq[String] = Nil,
patterns: Seq[String] = Nil,
callback: Boolean => Unit)
extends RedisSubscriberActor(address, channels, patterns, Option(""), callback) {
def onMessage(message: Message): Unit = {
// stuff
}
}
The problem is that I don't need this object to be instantiated when I run tests in Jenkins. Due of that, my tests failed because are trying to connect to a redis server which I use on localhost (is setted in application.conf
). I just want to ignore this object in my tests, because anyway, I don't use it.
How I instantiate the app in test file:
val app = new GuiceApplicationBuilder().disable[StartUpService].build()
where StartUpService
is a singleton class. But fo objects, I can not disable it in this way.
[[37minfo[0m] p.a.i.l.c.CoordinatedShutdownSupport - Starting synchronous coordinated shutdown with ServerStoppedReason reason and 2147533000 milliseconds timeout [[37minfo[0m] p.c.s.AkkaHttpServer - Terminating server binding for /0.0.0.0:9001 [[37minfo[0m] p.c.s.AkkaHttpServer - Running provided shutdown stop hooks CONNECTING COMMAND FAILED, cause = Some(java.net.ConnectException: Connection timed out)
thx
Solution
Based on @Tim response, I found that the module
class instantiate some object in the app
class Module extends AbstractModule {
override def configure() = {
bind(classOf[StartUpService]).asEagerSingleton
bind(classOf[TraitRepository]).to(classOf[ClassRepository])
}
}
Due of StartUpService
class, where I instantiate a lot of services, all these are fired in all tests where I build the app object. The solution was to create a TestModule
(without StartUp class) and use it in overriding the first.
object TestModule extends AbstractModule {
override def configure() = {
bind(classOf[TraitRepository]).to(classOf[ClassRepository])
}
}
And now I can create the app object without firing all the services, as:
val app = new GuiceApplicationBuilder()
.disable[Module]
.overrides(TestModule)
.build()
CodePudding user response:
An object
is only initialised when a member of the object
is accessed, so you must be using at least one value in RedisPubSubService
in your tests.
The clean solution is to move all the values used in the tests into a separate class (RedisPubSubConfig
?) and only have the real service code in RedisPubSubService
. That way the service will only be created when it is used.
The tests can use a Mock service that is in a separate object
(RedisPubSubMock
?) that also uses RedisPubSubConfig
. The code in this object
will only be initialised during the tests.
Alternatively you can make the relevant val
s lazy
so they are only intialised when they are first used.