2013-11-12 4 views
1

Я после этой статьи, которая описывает, как достичь инъекции зависимостей в Scala через торт Pattern: http://jonasboner.com/real-world-scala-dependency-injection-di/Scala Dependency Injection с тортом Pattern

Я вроде новичок в Scala, и я признаю, некоторые из них пошел над моей головой, до сих пор я получил следующую работу:

// Setup the component and interface 
trait AccountRepositoryComponent { 
    val accountRepository: AccountRepositoryInterface 

    trait AccountRepositoryInterface { 
    def message: String 
    } 
} 

// An implementation 
trait MyAccountRepositoryComponent extends AccountRepositoryComponent { 
    object AccountRepository extends AccountRepositoryInterface { 
    def message: String = "Hello" 
    } 
} 

// Object to configure which implementations to use and retrieve them 
object ComponentRegistry extends MyAccountRepositoryComponent { 
    val accountRepository = AccountRepository 
} 

// Example service using the above 
object AccountService { 
    val repo = ComponentRegistry.accountRepository 
    def say: String = repo.message 
} 

println(AccountService.say) 

То, что я не в состоянии понять, как я бы сейчас передать в поддельном хранилище для учетной записи службы, скажем, изменить выход на " Test ", а не" Hello "?

ответ

3

Существуют различные способы изменения этого параметра для достижения работоспособного результата в зависимости от того, что считается результативным для вашей ситуации. Я рассмотрю более простую возможность.

Во-первых, ComponentRegistry должен стать признаком, так что он может быть смешан в к AccountService:

// Trait to configure which component implementations to use and retrieve them 
object ComponentRegistry extends MyAccountRepositoryComponent { 
    val accountRepository = AccountRepository 
} 

// Example service using the above 
object AccountService extends ComponentRegistry { 
    def say: String = accountRepository.message 
} 

println(AccountService.say) 

Это должно напечатать «Hello», как и раньше. Для того, чтобы создать тестовый случай, добавьте следующее:

// Test implementation 
trait TestAccountRepositoryComponent extends AccountRepositoryComponent { 
    object AccountRepository extends AccountRepositoryInterface { 
    def message: String = "Test" 
    } 
} 

// trait to configure test component implementations 
trait TestComponentRegistry extends TestAccountRepositoryComponent { 
    val accountRepository = AccountRepository 
} 

Теперь мы можем создать службу, которая использует компоненты теста:

// Example service using the above 
object AccountService extends TestComponentRegistry { 
    //val repo = ComponentRegistry.accountRepository 
    def say: String = accountRepository.message 
} 

println(AccountService.say) 

Это должно напечатать «Test».

Обратите внимание, что вы, вероятно, захотите, чтобы ваш AccountService определил его функциональность с точки зрения других миксингов/признаков, которые ожидали бы, что соответствующие компоненты будут доступны (накладываются на «торт»), но не знают, какая реализация была в использовании. Например:

trait CustomerApi { 
    self: AccountRepositoryComponent => // Expects an implementation of AccountRepositoryComponent to be mixed in 

    def say: String = accountRepository.message 
} 

Теперь метод say реализован, не зная, какая версия AccountRepository он будет взаимодействовать, но, зная, один должен быть обеспечен (проверяется во время компиляции). Таким образом, мы можем написать:

object AccountService extends CustomerApi with ComponentRegistry 
object TestAccountService extends CustomerApi with TestComponentRegistry 

Вызов println(AccountService.say) будет генерировать "Hello", при вызове println(TestAccountService.say) будет генерировать "Test".

+0

Спасибо, поэтому его более смешивание, чем фактическая инъекция? основанный на этом, что было бы лучшим способом издеваться над AccountRepository для теста? (предполагая specs2/Mockito) – matthewrk

+0

Получил это, я пытался издеваться над объектом, если я издеваюсь над «Интерфейсом», но он отлично работает. – matthewrk

0

This post дает краткий пример этого (за которым следует интересная альтернатива).

Смежные вопросы