Categories
未分类

Android单元测试(六):使用dagger2来做依赖注入,以及在单元测试中的应用

注: 1. 代码中的 //<= 表示新加的、修改的等需要重点关注的代码 2. Class#method表示一个类的instance method,比如 LoginPresenter#login 表示 LoginPresenter的login(非静态)方法。 ## 问题 在前一篇文章中,我们讲述了依赖注入的概念,以及依赖注入对单元测试极其关键的重要性和必要性。在那篇文章的结尾,我们遇到了一个问题,那就是如果不使用DI框架,而全部采用手工来做DI的话,那么所有的Dependency都需要在最上层的client来生成,这可不是件好事情。继续用我们前面的例子来具体说明一下。 假设有一个登录界面,LoginActivity,他有一个LoginPresenter,LoginPresenter用到了UserManager和PasswordValidator,为了让问题变得更明显一点,我们假设UserManager用到SharedPreference(用来存储一些用户的基本设置等)和UserApiService,而UserApiService又需要由Retrofit创建,而Retrofit又用到OkHttpClient(比如说你要自己控制timeout、cache等东西)。 应用DI模式,UserManager的设计如下: public class UserManager { private final SharedPreferences mPref; private final UserApiService mRestAdapter; public UserManager(SharedPreferences preferences, UserApiService userApiService) { this.mPref = preferences; this.mRestAdapter = userApiService; } /**Other code*/ } LoginPresenter的设计如下: public class LoginPresenter { private final UserManager mUserManager; private final […]

Categories
未分类

Android单元测试(五):依赖注入,将mock方便的用起来

在上一篇文章中,我们讲了要将mock出来的dependency真正使用起来,需要在测试环境下通过某种方式set 到用到它的那个对象里面进去,替换掉真实的实现。我们前面举的例子是: public class LoginPresenter { private UserManager mUserManager = new UserManager(); public void login(String username, String password) { //。。。some other code mUserManager.performLogin(username, password); } } 在测试LoginPresenter#login()时,为了能够将mock出来的UserManager set到LoginPresenter里面,我们前面的做法是简单粗暴,给LoginPresenter加一个UserManager的setter。然而这种做法毕竟不是很优雅,一般来说,我们正式代码里面是不会去调用这个setter,修改UserManager这个对象的。因此这个setter存在的意义就纯粹是为了方便测试。这个虽然不是没有必要,却不是太好看,因此在有选择的情况下,我们不这么做。在这里,我们介绍依赖注入这种模式。 对于依赖注入(Dependency Injection,以下简称DI)的准确定义可以在这里找到。它的基本理念这边简单描述下,首先这是一种代码模式,这个模式里面有两个概念:Client和Dependency。假如你的代码里面,一个类用到了另外一个类,那么前者叫Client,后者叫Dependency。结合上面的例子,LoginPresenter用到了UserManager,那么LoginPresenter叫Client,UserManager叫Dependency。当然,这是个相对的概念,一个类可以是某个类的Dependency,却是另外一个类的Client。比如说如果UserManager里面用到了Retrofit,那么相对于Retrofit,UserManager又是Client。DI的基本思想就是,对于Dependency的创建过程,并不在Client里面进行,而是由外部创建好,然后通过某种方式set到Client里面。这种模式,就叫做依赖注入。 是的,依赖注入就是这么简单的一个概念,这边需要澄清的一点是,这个概念本身跟dagger2啊,RoboGuice这些框架并没有什么关系。现在很多介绍DI的文章往往跟dagger2是在一起的,因为dagger2的使用相对来说不是很直观,所以导致很多人认为DI是多么复杂的东西,甚至认为只能用dagger等框架来实现依赖注入,其实不是这样的。实现依赖注入很简单,dagger这些框架只是让这种实现变得更加简单,简洁,优雅而已。 ## DI的常见实现方式 下面介绍DI的实现方式,通常来说,这里是大力介绍dagger2的地方。但是,虽然dagger2的确是非常好的东西,然而如果我直接介绍dagger2的话,会很容易导致一个误区,认为在测试的时候,也只能用dagger来做依赖注入或创建对应的测试类,因此,我这边刻意不介绍dagger。先让大家知道最基本的DI怎么实现,然后在测试的时候如何更方便高效的使用。 实现DI这种模式其实很简单,有多种方式,上一篇文章中提到的setter,其实就是实现DI的一种方式,叫做 setter injection 。此外,通过方法的参数传递进去(argument injection),也是实现DI的一种方式: public class LoginPresenter { //这里,LoginPresenter不再持有UserManager的一个引用,而是作为方法参数直接传进去 public void login(UserManager userManager, String username, String password) { //… some […]

Categories
未分类

2016年第一次百日计划总结

今年年初,1月2日,我拉了一个群,跟其他24个小伙伴一起做了件事,叫100天计划。这是在“warfalcon”这个公众号看到的一种做法,基本大意就是在100天之内,每天坚持做同一件事情。关于100天计划的具体说明可以在这里跟这里找到。其实这也不是我第一次做这件事情了,去年的时候就执行过一次,当时给自己定的项目是每天看英文书局1个小时。但是那次执行的比较混乱,最后花了130多天才完成,也没有记录得很好。 这次我给自己定的项目是“每天阅读或写作一个小时”,依然不是100%的坚持,很多时候也会偷懒,最后花了114天完成。最后坚持下来的有10个人,其中有3个小伙伴做到了100%坚持,每一天都完成了,也没有请过一天假,真是神一样的存在。 Anyway,我在这期间做完的事情如下: ## 看书 看完了的(后面是评分) Learned Optimism ☆☆☆☆☆ 被讨厌的勇气 ☆☆☆☆☆ 楚亡 ☆☆☆☆☆ 野火集 ☆☆☆☆☆ Matz程序世界 ☆☆☆☆ 旅行的意义 ☆☆☆☆ 月亮与六便士 ☆☆☆☆ 领导梯队 ☆☆☆☆ 亲爱的安德烈 ☆☆☆☆ 没看完的(后面是看完的部分) Android框架解密(40%) Clean code(40%) 说话的魅力(50%) 貌似都是非技术类的,而技术类的,额。。。 ## 写文章### 非技术文章 读《亲爱的安德烈》– 想要这样一段不煽情,不鸡汤,不说教的家书来往 读《野火集》– 民主和文明,需要我们自己去争取 【7分钟乐读会】第24期书籍分享小结 Life is short ### 技术文章 android单元测试在微信群的分享 文章版 FactoryGirl在Rails中的使用 《Clean Code》阅读:在大师们的眼中,什么样的Code才是Clean Code? 《Clean Code》第二章:命名是件大事情 Android单元测试: 首先,从是什么开始 Android单元测试(二):再来谈谈为什么 […]