第一步:build.gradle文件添加测试相关依赖
dependencies {
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.19.0'
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0'//mock()
testImplementation 'org.mockito:mockito-inline:2.13.0'//适配单元测试时,不能调用final类
...
}
第二步新建测试类(项目中存在的类)
BasePresenter:
packagecom.example.testabstractclassBasePresenter{protectedvarview: V? =nullfunattachView(view:V){this.view = view }fundetachView(){this.view =null}}
Recipe:
packagecom.example.testclassRecipe(varid : String ="",vartitle :String ="",varimageUrl : String ="",varsourceUrl : String ="",varisFavorited :Boolean=false)
RecipeRepository:
packagecom.example.testinterfaceRecipeRepository{funaddFavorite(item:Recipe)funremoveFavorite(item:Recipe)fungetFavoriteRecipes(): ListfungetRecipes(query:String, callback:RepositoryCallback>)}interfaceRepositoryCallback{funonSuccess(t:T?)funonError()}
SearchResultsPresenter:
packagecom.example.test/**
* JunitTestClass
*/classSearchResultsPresenter(privatevalrepository: RecipeRepository) : BasePresenter() {privatevarrecipes: List? =nullfunsearch(query:String){ view?.showLoading() repository.getRecipes(query,object: RepositoryCallback> {overridefunonSuccess(recipes:List?){this@SearchResultsPresenter.recipes = recipesif(recipes !=null&& recipes.isNotEmpty()) { view?.showRecipes(recipes) }else{ view?.showEmptyRecipes() } }overridefunonError(){ view?.showError() } }) }funaddFavorite(recipe:Recipe){ recipe.isFavorited =truerepository.addFavorite(recipe)valrecipeIndex = recipes?.indexOf(recipe)if(recipeIndex !=null) { view?.refreshFavoriteStatus(recipeIndex) } }funremoveFavorite(recipe:Recipe){ repository.removeFavorite(recipe) recipe.isFavorited =falsevalrecipeIndex = recipes?.indexOf(recipe)if(recipeIndex !=null) { view?.refreshFavoriteStatus(recipeIndex) } }interfaceView{funshowLoading()funshowRecipes(recipes:List)funshowEmptyRecipes()funshowError()funrefreshFavoriteStatus(recipeIndex:Int)}}
第三步:给presenter新建测试类
1>、windows快捷键:ctrl+shift+T(也可鼠标右键->go to->Test);
2>、接着有测试类会让你选择,没有的->create new test...;
3>
4>新建成功
第四步:编写测试方法
1>verify方法(@Before将在@Test等方法之前调用)
classSearchResultsPresenterTest{privatelateinitvarrepository: RecipeRepositoryprivatelateinitvarpresenter: SearchResultsPresenterprivatelateinitvarview: SearchResultsPresenter.View@Before//最先调用(初始化)funsetup(){ repository = mock() view = mock() presenter = SearchResultsPresenter(repository) presenter.attachView(view) }@Testfunsearch_callsShowLoading(){ presenter.search("eggs")// verify(view).showLoading()//验证搜索时showLoading会不会被调用到verify(view).showEmptyRecipes()//验证showEmptyRecipes会不会被调用到// verify(view).showRecipes(mock())//验证showRecipes会不会被调用到}}
如果verify方法验证了这次运行未调用此方法,运行后将会抛出错误,便于我们验证是否运行后调用该方法(如果调用了,日志没有反应)
同时刚才我们的coverage运行结果可以直接查看方法被调用的情况
2、doAnswer方法(插桩):
@Testfunsearch_callShowRecipes(){valrecipe = Recipe("id","title","imageUrl","sourceUrl",false)valrecipes = listOf(recipe) doAnswer {//执行相应的方法(getRecipes)并拿到回调(Stubbing--插桩)valcallback: RepositoryCallback> = it.getArgument(1)// callback.onSuccess(recipes)//此时以下的verify将会全部通过callback.onError()//这里也可以用onError()方法验证(此时下面的verify(view).showRecipes(eq(recipes))将会抛出错误)}.whenever(repository).getRecipes(eq("eggs"), any()) presenter.search("eggs") verify(repository).getRecipes(eq("eggs"), any()) verify(view).showRecipes(eq(recipes)) }
通过doAnswer方法和verify方法,我们可以验证代码是否正确调用了正确的方法(行为验证)
3:Assert 方法:
@TestfunaddFavorite_shouldUpdateRecipeStatus(){valrecipe = Recipe("id","title","imageUrl","sourceUrl",false) presenter.addFavorite(recipe)//状态验证,assertThat(T actual, Matcher<? super T> matcher)左边为待验证的字段,右边为匹配器,// is是kotlin关键字,所以'is'。如果验证字段不同将会抛出错误。Assert.assertThat(recipe.isFavorited, CoreMatchers.`is`(false)) }
状态验证,assertThat(T actual, Matcher<? super T> matcher)左边为待验证的字段,右边为匹配器,is是kotlin关键字,所以'is';
@TestfunremoveFavorite_shouldUpdateRecipeStatus(){valrecipe = Recipe("id","title","imageUrl","sourceUrl",true) presenter.removeFavorite(recipe) Assert.assertThat(recipe.isFavorited, CoreMatchers.`is`(false)) }
参考连接:
网友评论