问题描述
我为我的 Presenter 编写单元测试,这需要模拟我的本地数据源.
I write unit test for my Presenter, which is need to mock my Local Data Source.
这是我的简单测试:
public class AddressPresenterTest {
@Mock
private AddressView mView;
@Mock
private AddressDataSource mDataSource;
@Mock
private AddressLocalDataSource mLocalDataSource;
@Captor
ArgumentCaptor<DataSourceCallback<Province>> mProvinceCallbackCaptor;
private AddressPresenter mPresenter;
@Before
public void beforeTest() {
MockitoAnnotations.initMocks(this);
mPresenter = new AddressPresenter(mDataSource, mView);
mPresenter.setLocalDataSource(mLocalDataSource);
}
@Test
public void When_SelectProvince_DataIsNull_ShowErrorMessage() {
mPresenter.getLocalProvinceById(2129023);
// Cause data source has callback, we need to capture the callback
ArgumentCaptor<Integer> provinceIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mLocalDataSource).fetchProvinceById(provinceIdCaptor.capture(), mProvinceCallbackCaptor.capture());
mProvinceCallbackCaptor.getValue().onFailedLoad();
verify(mView).loadContentError();
}
}
当我运行这个测试时,我得到了错误,
When i run this test i got the error,
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class com.dai.uangteman.data.AddressLocalDataSource.
Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.
Java : 1.8
JVM vendor name : Oracle Corporation
JVM vendor version : 25.77-b03
JVM name : Java HotSpot(TM) 64-Bit Server VM
JVM version : 1.8.0_77-b03
JVM info : mixed mode
OS name : Mac OS X
OS version : 10.12.6
Underlying exception : java.lang.IllegalArgumentException: Could not create type
at com.dai.uangteman.view.fragment.presenter.AddressPresenterTest.beforeTest(AddressPresenterTest.java:41)
...
Caused by: java.lang.IllegalArgumentException: Could not create type
at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:140)
... 28 more
Caused by: java.lang.NoClassDefFoundError: android/database/sqlite/SQLiteOpenHelper
at java.lang.ClassLoader.defineClass1(Native Method)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:138)
... 45 more
Caused by: java.lang.ClassNotFoundException: android.database.sqlite.SQLiteOpenHelper
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
... 87 more
当我改变我的 AddressLocalDataSource
类时,我发现了一些奇怪的东西.
When i workaround to change my AddressLocalDataSource
class i found something weird.
public class AddressLocalDataSource {
private StaticDatabaseHelper mDatabaseHelper;
// /**
// * @param mDatabaseHelper
// */
// public AddressLocalDataSource(StaticDatabaseHelper mDatabaseHelper) {
// this.mDatabaseHelper = mDatabaseHelper;
// }
public void setDatabaseHelper(StaticDatabaseHelper mDatabaseHelper) {
this.mDatabaseHelper = mDatabaseHelper;
}
...
}
低于我的发现:
- 我尝试删除包含
StaticDatabaseHelper
对象参数的构造函数和 setter 方法,它可以工作! - 我尝试更改 setter 方法中的
StaticDatabaseHelper
初始化它不起作用!
- I try to remove my constructor and setter method which is contain
StaticDatabaseHelper
object parameter and it works! - I try to change the
StaticDatabaseHelper
initialization in setter method it doesn't work!
问题是我的 AddressLocalDataSource
需要 StaticDatabaseHelper
类的实例.
The problem is my AddressLocalDataSource
need instance of StaticDatabaseHelper
class.
有什么想法吗?谢谢
推荐答案
在我寻找解决方案几个小时后,我得到了最简单的解决方案.我认为android库中有一些不完整的测试.所以我只是运行这个 gradle 命令来清理:
After a couple hour i looking for solution, i get the simplest solution.I think there is some incomplete in android library for testing. So i just run this gradle command to cleanup :
./gradlew clean test
它现在可以工作了,在这种情况下我只是模拟 StaticDatabaseHelper
类.所以这是我最后的测试Class:
And it works now, i just mock StaticDatabaseHelper
class in this case.So this is my final testing Class :
public class AddressPresenterTest {
@Mock
private AddressView mView;
@Mock
private AddressDataSource mDataSource;
@Mock
private AddressLocalDataSource mLocalDataSource;
@Captor
ArgumentCaptor<DataSourceCallback<Province>> mProvinceCallbackCaptor;
private AddressPresenter mPresenter;
@Before
public void beforeTest() throws Exception {
MockitoAnnotations.initMocks(this);
mPresenter = new AddressPresenter(mDataSource, mView);
mPresenter.setLocalDataSource(mLocalDataSource);
}
@Test
public void When_SelectProvince_DataIsNull_ShowErrorMessage() {
mPresenter.getLocalProvinceById(2129023);
// Cause data source has callback, we need to capture the callback
ArgumentCaptor<Integer> provinceIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mLocalDataSource).fetchProvinceById(provinceIdCaptor.capture(), mProvinceCallbackCaptor.capture());
mProvinceCallbackCaptor.getValue().onFailedLoad();
verify(mView).loadContentError();
}
}
希望能帮到你,谢谢
这篇关于错误模拟持有对 SQLiteOpenHelper 的引用的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!