Skip to content

Commit

Permalink
单元测试调整
Browse files Browse the repository at this point in the history
  • Loading branch information
K0170016 authored and K0170016 committed Jul 4, 2019
1 parent aa986cb commit 3e6a45e
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ class ArticleStore @Inject constructor(rxDispatcher: RxDispatcher) : RxActivityS
bannerLiveData.value = null
}

/**
* 接收BannerList数据
*/
@Subscribe(tags = [ArticleAction.GET_BANNER_LIST])
fun setBannerLiveData(rxAction: RxAction) {
fun onGetBannerLiveData(rxAction: RxAction) {
val bannerResponse = rxAction.getResponse<WanResponse<ArrayList<Banner>>>()
bannerLiveData.value = bannerResponse!!.data
}

/**
* 接收ArticleList数据
*/
@Subscribe(tags = [ArticleAction.GET_ARTICLE_LIST])
fun setArticleLiveData(rxAction: RxAction) {
fun onGetArticleLiveData(rxAction: RxAction) {
val articleResponse = rxAction.getResponse<WanResponse<Page<Article>>>()
if (articleLiveData.value == null) {
articleLiveData.setValue(articleResponse!!.data!!.datas)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,20 @@ package com.huyingbao.module.wan.ui.article.view

import android.os.Bundle
import androidx.fragment.app.Fragment

import com.alibaba.android.arouter.facade.annotation.Route
import com.huyingbao.core.arch.model.RxChange
import com.huyingbao.core.base.activity.BaseRxFragActivity
import com.huyingbao.core.common.module.CommonContants
import com.huyingbao.module.wan.app.WanAppStore
import com.huyingbao.module.wan.ui.article.action.ArticleAction
import com.huyingbao.module.wan.ui.article.store.ArticleStore
import com.huyingbao.module.wan.ui.friend.view.FriendFragment

import org.greenrobot.eventbus.Subscribe

import javax.inject.Inject

/**
* Created by liujunfeng on 2019/1/1.
*/
@Route(path = CommonContants.Address.ArticleActivity)
class ArticleActivity : BaseRxFragActivity<ArticleStore>() {
@Inject
lateinit var wanAppStore: WanAppStore

override fun createFragment(): Fragment? {
return ArticleListFragment.newInstance()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,36 @@ import org.junit.runners.model.Statement

/**
* [com.huyingbao.core.arch.store.RxStore]和[com.huyingbao.core.arch.view.RxSubscriberView]
* 自动注册订阅和取消订阅
* 自动注册订阅和取消订阅。
*
* Created by liujunfeng on 2019/7/1.
*/
class BaseActionCreatorRule : MethodRule {
class BaseSubscriberRule : MethodRule {
override fun apply(base: Statement?, method: FrameworkMethod?, target: Any?): Statement {
return object : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
if (target is BaseActionCreatorTest) {
if (target is BaseSubscriberTest) {
//获取需要注册订阅的对象列表
for (subscriber in target.getSubscriberList()) {
if (subscriber is RxStore) {
//注册订阅RxStore
target.rxDispatcher.subscribeRxStore(subscriber)
} else if (subscriber is RxSubscriberView) {
//注册订阅RxSubscriberView
target.rxDispatcher.subscribeRxView(subscriber)
}
}
}
base?.evaluate()
if (target is BaseActionCreatorTest) {
if (target is BaseSubscriberTest) {
//获取需要取消订阅的对象列表
for (subscriber in target.getSubscriberList()) {
if (subscriber is RxStore) {
//取消订阅RxStore
target.rxDispatcher.unsubscribeRxStore(subscriber)
} else if (subscriber is RxSubscriberView) {
//取消订阅RxSubscriberView
target.rxDispatcher.unsubscribeRxView(subscriber)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import org.mockito.Spy
import org.mockito.junit.MockitoJUnit

/**
* 所有ActionCreator测试类的父类
* 所有Subscriber测试类的父类
*
* Created by liujunfeng on 2019/4/3.
*/
abstract class BaseActionCreatorTest {
abstract class BaseSubscriberTest {
/**
* 初始化DaggerMock
*/
Expand All @@ -28,7 +28,7 @@ abstract class BaseActionCreatorTest {
* 自动注册订阅和取消订阅
*/
@get:Rule
var actionCreatorRule = BaseActionCreatorRule()
var actionCreatorRule = BaseSubscriberRule()
/**
* RxJava调度器异步转为同步
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.huyingbao.module.wan.module
import it.cosenonjaviste.daggermock.DaggerMock

/**
* 全局静态方法,提供依赖注入器实例对象
* 全局静态方法,提供依赖注入器实例对象。
*
* Created by liujunfeng on 2019/7/1.
*/
object MockUtils {
var component: MockComponent? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton

/**
* 依赖注入器,为测试代码提供方便测试的全局对象
* 依赖注入器,为测试代码提供方便测试的全局对象。
*
* Created by liujunfeng on 2019/7/1.
*/
@Singleton
@Component(modules = [MockModule::class])
Expand All @@ -41,16 +43,26 @@ interface MockComponent {
*/
@Module(includes = [CommonModule::class, WanAppModule::class])
class MockModule {
/**
* 返回实际创建的[ArticleStore]实例对象,但是DaggerMock会返回虚拟的Mock对象,参见[mockDaggerRule]方法。
* 如果[MockComponent]不定义该对象,该方法不会被调用。
*
* @param rxStoreFactory 来自[CommonModule],[ArticleStore]对象来自[WanAppModule]
*/
@Singleton
@Provides
fun provideArticleStore(rxStoreFactory: ViewModelProvider.Factory): ArticleStore {
return rxStoreFactory.create(ArticleStore::class.java)
}

/**
* 初始化Retrofit
*
* @param builder 来自[CommonModule]
*/
@Singleton
@Provides
fun provideRetrofit(builder: OkHttpClient.Builder): Retrofit {
//初始化Retrofit
val retrofitBuilder = Retrofit.Builder()
.baseUrl(WanContants.Base.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().serializeNulls().create()))
Expand All @@ -68,8 +80,6 @@ class MockModule {

/**
* 使用RESTMockServer,为需要测试的接口提供mock数据
*
* @return mock的url
*/
private fun initMockServer(): String {
//开启RestMockServer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.huyingbao.module.wan.ui.article.action

import com.huyingbao.module.wan.module.BaseActionCreatorTest
import com.huyingbao.module.wan.module.BaseSubscriberTest
import com.huyingbao.module.wan.module.MockUtils
import com.huyingbao.module.wan.ui.article.store.ArticleStore
import com.nhaarman.mockitokotlin2.any
Expand All @@ -9,7 +9,13 @@ import org.junit.Before
import org.junit.Test
import org.mockito.Mock

class ArticleActionCreatorTest : BaseActionCreatorTest() {
/**
* 实际调用接口方法,Mock[com.huyingbao.core.arch.store.RxStore]和[com.huyingbao.core.arch.view.RxSubscriberView],
* 验证方法调用之后[com.huyingbao.core.arch.store.RxStore]和[com.huyingbao.core.arch.view.RxSubscriberView]得到响应。
*
* Created by liujunfeng on 2019/3/28.
*/
class ArticleActionCreatorTest : BaseSubscriberTest() {
@Mock
lateinit var articleStore: ArticleStore

Expand All @@ -26,12 +32,19 @@ class ArticleActionCreatorTest : BaseActionCreatorTest() {

@Test
fun getArticleList() {
//调用接口
articleActionCreator?.getArticleList(1)
//验证接口调用成功,发送数据
verify(rxDispatcher).postRxAction(any())
verify(articleStore).setArticleLiveData(any())
//验证RxStore接收到数据,因为RxStore是mock的,故该方法并不会通知View更新数据
verify(articleStore).onGetArticleLiveData(any())
}

@Test
fun getBannerList() {
//调用接口
articleActionCreator?.getBannerList()
//验证RxStore接收到数据,因为RxStore是mock的
verify(articleStore).onGetBannerLiveData(any())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,44 @@ import androidx.lifecycle.Lifecycle
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.huyingbao.module.wan.R
import com.huyingbao.module.wan.WanApplication

import org.junit.Rule
import org.junit.Test
import org.junit.*
import org.junit.runner.RunWith
import org.robolectric.annotation.Config

/**
* Robolectric配合Espresso使用,实际运行scenario对应的方法。
* build.gradle配置test src之后,Robolectric使用当前model作为App时的[WanApplication]和AndroidManifest.xml文件。
*
* Created by liujunfeng on 2019/3/28.
*/
@LargeTest
@RunWith(AndroidJUnit4::class)
@Config(application = WanApplication::class)
class ArticleActivityTest {
@get:Rule
var activityRule: ActivityScenarioRule<ArticleActivity> = ActivityScenarioRule(ArticleActivity::class.java)
var scenarioRule = ActivityScenarioRule(ArticleActivity::class.java)

@Before
fun setUp() {
//Activity场景移动到Lifecycle.State.CREATED
scenarioRule.scenario.moveToState(Lifecycle.State.CREATED)
}

@After
fun tearDown() {
//Activity场景移动到Lifecycle.State.DESTROYED
scenarioRule.scenario.moveToState(Lifecycle.State.DESTROYED)
}

@Test
fun onRxChanged() {
activityRule.scenario.moveToState(Lifecycle.State.CREATED)
fun afterCreate() {
scenarioRule.scenario.moveToState(Lifecycle.State.RESUMED)
scenarioRule.scenario.onActivity {
//验证ArticleListFragment已经添加到当前Activity中
val fragment = it.supportFragmentManager.findFragmentById(R.id.fl_container)
Assert.assertTrue(fragment is ArticleListFragment)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,25 @@ class ArticleListFragmentTest {

@Test
fun getArticleActionCreator() {
//验证articleActionCreator已经依赖注入
scenarioRule.scenario.onFragment { Assert.assertNotNull(it.articleActionCreator) }
}

@Test
fun getLayoutId() {
//验证布局文件已经设置
scenarioRule.scenario.onFragment { Assert.assertNotNull(it.getLayoutId()) }
}

@Test
fun afterCreate() {
scenarioRule.scenario.moveToState(Lifecycle.State.RESUMED)
scenarioRule.scenario.onFragment {
//验证Fragment中R.id.rv_content对应的View显示
Espresso.onView(ViewMatchers.withId(R.id.rv_content))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))

//验证Fragment持有的Store在接口调用成功之后,更新其维持的LiveData数据
Assert.assertTrue(it.rxStore?.articleLiveData?.value?.size!! > 0)
}
}
}

0 comments on commit 3e6a45e

Please sign in to comment.