简体   繁体   English

单元测试AKKA演员

[英]Unit Testing AKKA actors

I am doing a web application with Scala and Akka actors and I'm having some troubles with the tests . 我正在与ScalaAkka演员一起制作Web应用程序,但在tests遇到了一些麻烦。

In my case I need to taste an actor who talks with the Database. 就我而言,我需要品尝与数据库对话的演员。 To do the unit testing I would like to use a Fake Database but I can't replace the new with my desired fake object. 为了进行单元测试,我想使用伪数据库,但是不能用所需的假对象替换新的数据库。

Let's see some code: 让我们看一些代码:

Class MyActor extends Actor {
    val database = new Database()

    def receive = { ... }
}

And in the tests I would like to inject a FakeDatabase object instead Database. 在测试中,我想注入一个FakeDatabase对象而不是Database。 I've been looking in Internet but the best that I found is: 我一直在寻找Internet,但是发现的最好结果是:

  • Add a parameter to the constructor. 向构造函数添加参数。
  • Convert the val database to a var so in the test I could access the attribute by the underlying and replace it. val数据库转换为var以便在测试中我可以通过基础访问属性并将其替换。

Both solutions solve the problem but are very dirty. 两种解决方案都可以解决问题,但是非常麻烦。

Isn't a better way to solve the problem? 解决问题不是更好的方法吗?

Thanks! 谢谢!

The two primary options for this scenario are: 此方案的两个主要选项是:

  1. Dependency Injection Use a DI framework to inject a real or mock service as needed. 依赖项注入根据需要使用DI框架注入真实或模拟服务。 In Akka: http://letitcrash.com/post/55958814293/akka-dependency-injection 在Akka中: http : //letitcrash.com/post/55958814293/akka-dependency-injection

  2. Cake Pattern This is a Scala-specific way of achieving something akin to dependency injection without actually relying on injection. Cake Pattern这是一种Scala特定的方式,可以在不实际依赖注入的情况下实现类似于依赖注入的功能。 See: Akka and cake pattern 请参阅: Akka和蛋糕图案

Echoing the advice here, I wouldn't call injecting the database in the constructor dirty. 在这里回荡建议,我不会将注入构造函数中的数据库称为肮脏的。 It might have plenty of benefits, including decoupling actor behaviour from the particular database instance. 它可能具有很多好处,包括将参与者的行为与特定的数据库实例脱钩。

However if you know there is only ONE database you will be always using in your production code, then think about defining a package level accessible constructor and a companion object returning a Props object without parameters by default. 但是,如果您知道在生产代码中将始终使用一个数据库,那么请考虑定义一个程序包级别可访问的构造函数和一个默认情况下返回不带参数的Props对象的伴随对象。

Example below: 下面的例子:

object MyActor {

    def props() : Props = Props(new MyActor(new Database()))

}

class MyActor private[package](database : IDatabase) extends Actor {

    def receive = { ... }
}

In this case you will still be able to inject the test database in your tests case (given the same package structure), but prevent users of your code from instantiating MyActor with unexpected database instance. 在这种情况下,您仍然可以在测试案例中注入测试数据库(给定相同的包结构),但是可以防止您的代码用户使用意外的数据库实例实例化MyActor

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM