避免在测试文件中实例化对象
Avoiding to instantiate object in test files
我有一个 Redis PubSub 对象:
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
}
}
问题是当我 运行 在 Jenkins 中测试时,我不需要实例化这个对象。因此,我的测试失败了,因为我试图连接到我在本地主机上使用的 redis 服务器(在 application.conf
中设置)。我只是想在我的测试中忽略这个对象,因为无论如何,我不使用它。
我如何在测试文件中实例化应用程序:
val app = new GuiceApplicationBuilder().disable[StartUpService].build()
其中 StartUpService
是单例 class。但是对于对象,我不能以这种方式禁用它。
[[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)
感谢
Solution
根据@Tim 的回复,我发现 module
class 在应用程序中实例化了一些对象
class Module extends AbstractModule {
override def configure() = {
bind(classOf[StartUpService]).asEagerSingleton
bind(classOf[TraitRepository]).to(classOf[ClassRepository])
}
}
由于 StartUpService
class,我实例化了很多服务,所有这些都在我构建应用程序对象的所有测试中触发。解决方案是创建一个 TestModule
(没有 StartUp class)并用它覆盖第一个。
object TestModule extends AbstractModule {
override def configure() = {
bind(classOf[TraitRepository]).to(classOf[ClassRepository])
}
}
现在我可以在不触发所有服务的情况下创建应用程序对象,如:
val app = new GuiceApplicationBuilder()
.disable[Module]
.overrides(TestModule)
.build()
object
仅在访问 object
的成员时初始化,因此您必须在测试中至少使用 RedisPubSubService
中的一个值。
干净的解决方案是将测试中使用的所有值移动到单独的 class(RedisPubSubConfig
?)中,并且只有 RedisPubSubService
中有真正的服务代码。这样服务只会在使用时创建。
测试可以使用单独的 object
(RedisPubSubMock
?)中的 Mock 服务,该服务也使用 RedisPubSubConfig
。此 object
中的代码只会在测试期间初始化。
或者,您可以制作相关的 val
s lazy
,这样它们只会在首次使用时被初始化。
我有一个 Redis PubSub 对象:
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
}
}
问题是当我 运行 在 Jenkins 中测试时,我不需要实例化这个对象。因此,我的测试失败了,因为我试图连接到我在本地主机上使用的 redis 服务器(在 application.conf
中设置)。我只是想在我的测试中忽略这个对象,因为无论如何,我不使用它。
我如何在测试文件中实例化应用程序:
val app = new GuiceApplicationBuilder().disable[StartUpService].build()
其中 StartUpService
是单例 class。但是对于对象,我不能以这种方式禁用它。
[[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)
感谢
Solution
根据@Tim 的回复,我发现 module
class 在应用程序中实例化了一些对象
class Module extends AbstractModule {
override def configure() = {
bind(classOf[StartUpService]).asEagerSingleton
bind(classOf[TraitRepository]).to(classOf[ClassRepository])
}
}
由于 StartUpService
class,我实例化了很多服务,所有这些都在我构建应用程序对象的所有测试中触发。解决方案是创建一个 TestModule
(没有 StartUp class)并用它覆盖第一个。
object TestModule extends AbstractModule {
override def configure() = {
bind(classOf[TraitRepository]).to(classOf[ClassRepository])
}
}
现在我可以在不触发所有服务的情况下创建应用程序对象,如:
val app = new GuiceApplicationBuilder()
.disable[Module]
.overrides(TestModule)
.build()
object
仅在访问 object
的成员时初始化,因此您必须在测试中至少使用 RedisPubSubService
中的一个值。
干净的解决方案是将测试中使用的所有值移动到单独的 class(RedisPubSubConfig
?)中,并且只有 RedisPubSubService
中有真正的服务代码。这样服务只会在使用时创建。
测试可以使用单独的 object
(RedisPubSubMock
?)中的 Mock 服务,该服务也使用 RedisPubSubConfig
。此 object
中的代码只会在测试期间初始化。
或者,您可以制作相关的 val
s lazy
,这样它们只会在首次使用时被初始化。