我有一个社交对象,负责连接到 Twitter、Facebook 等,并检索指定用户的提供者信息
对于每个提供者,我实现了一个单例 TwitterAdapter,所有这些都继承自一个抽象类 SocialAdapter
对于测试,我显然想模拟 TwitterAdapter,这样它就不会与 twitter 连接,而是返回一些固定的响应。
我发现的一种解决方案是使用隐式参数注入适配器列表。此解决方案的问题在于 Social.retrieveSocialProviderInfo 是从其他函数调用的,因此我必须通过所有调用链传递隐式 List[SocialAdapter] 参数,如下所示:
def createApplicationToken(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters)
: Either[List[Error], ApplicationToken] = {
// go to social info provider and fetch information
retrieveProviderInfo(accessToken).fold(
[...]
def retrieveProviderInfo(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters)
: Either[List[Error], IdentityProviderInfo] = {
[...]
最后
object Social {
val defaultAdapters = List(TwitterAdapter, FacebookAdapter)
def retrieveSocialProviderInfo
(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters) // adapters can be injected
: Option[IdentityProviderInfo] = {
[...]
你明白了
它工作正常,通常我只是忽略第二组参数并从 Social.defaultAdapters 中选择默认值,我只在测试时将其设置为 List(MockTwitterAdapter, MockFacebookAdapter),但我只是为了能够测试它而将代码弄乱了.
另一种解决方案是将 Social.defaultAdapters 设置为 var(而不是 val)并更改它以进行测试,通常在生产模式下它总是具有相同的值。
我认为这一定是一个很常见的场景。有没有更好的策略来处理这些情况?或者也许是某种方式来扩展隐式赋值的范围?还是我应该使用功能齐全的依赖注入框架?