2014-04-07 4 views
0

Я делаю веб-приложение с Scala и Akka актерами, и у меня возникают проблемы с tests.Unit Testing Актеры AKKA

В моем случае мне нужно попробовать актера, который разговаривает с Базой данных. Для выполнения модульного тестирования я хотел бы использовать Fake Database, но я не могу заменить новый с помощью моего целевого поддельного объекта.

Давайте посмотрим код:

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

    def receive = { ... } 
} 

А в тестах я хотел бы, чтобы ввести объект FakeDatabase вместо базы данных. Я искал в Интернете, но лучшее, что я нашел, это:

  • Добавить параметр в конструктор.
  • Преобразование базы данных val в var, поэтому в тесте я мог получить доступ к атрибуту по базовому слову и заменить его.

Оба решения решают проблему, но очень загрязнены.

Не лучший способ решить эту проблему?

Спасибо!

+2

Я бы не назвал «добавление параметра в конструктор» грязным. Если вы думаете о семантике: может ли действующая функция без БД? Наверное, нет, поэтому конструктор - это очень хорошее место для него, потому что вы явно заявляете, что для создания актера ему нужна база данных. –

+0

Я не эксперт, но в вашем тесте вы можете переопределить базу данных следующим образом: new MyActor {override val database = new FakeDatabase} – user24601

+0

Я думаю, что он может работать, и это самое простое решение.Спасибо – mtrebi

ответ

0

два основных варианта этого сценария:

  1. Dependency Injection использовать структуру DI, чтобы придать реальный или макет службы по мере необходимости. В Акки: http://letitcrash.com/post/55958814293/akka-dependency-injection

  2. торт Pattern Это Scala-специфический способ достижения чего-то сродни инъекции зависимостей фактически не полагаться на инъекции. См: Akka and cake pattern

+0

Спасибо @Ryan!. Это то, что я искал. Я читаю ссылки, и я попробую. – mtrebi

0

Вторя советы здесь, я бы не назвал инъекционными базы данных в конструкторе грязного. Это может иметь много преимуществ, включая развязывание поведения актера из конкретного экземпляра базы данных.

Однако, если вы знаете, что существует только одна база данных, которую вы всегда будете использовать в своем производственном коде, подумайте о том, как определить конструктор доступного уровня пакета и объект-компаньон, по умолчанию возвращающий объект Props без параметров.

Пример ниже:

object MyActor { 

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

} 

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

    def receive = { ... } 
} 

В этом случае вы все равно будете иметь возможность вводить тестовую базу данных в тестах случае (при той же структуре пакета), но запретить пользователям вашего кода из инстанцировании MyActor с неожиданным экземпляр базы данных.

+0

Я уверен, что у нас будет более одной базы данных. Я также пытался избежать параметров в конструкторе по другим причинам в моем коде, который я не комментировал здесь, чтобы упростить эту проблему. В любом случае, я посмотрю. Спасибо @Norbert – mtrebi