【发布时间】:2019-10-01 08:38:36
【问题描述】:
我的视图模型拥有一个非常简单的 recyclerview 适配器
当我尝试向它发送消息(这反过来又调用notifyDatasetChanged)时,它会抛出这样的异常
java.lang.NullPointerException
at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:11996)
at
问题在于AdapterDataObservable 中的mObservers 变量为空
问题是这扩展了Observable<AdapterDataObserver>,而mObservers又定义为
protected final ArrayList<T> mObservers = new ArrayList<T>();
所以基本上在我的适配器被实例化的那一刻,它就会调用
private final AdapterDataObservable mObservable = new AdapterDataObservable();
(顺便调用,mObservable不为空)
反过来应该调用mObservers = new ArrayList<T>();
有人可以解释为什么从来没有调用它吗?或者是否有办法解决这个问题?
顺便说一句,适配器没有被模拟,它是一个实体对象。
编辑:
这是我正在使用的测试代码:
class LoginViewModelTest {
private lateinit var vm: LoginViewModel
@get:Rule
val rule = InstantTaskExecutorRule()
@Before
fun setUp() {
whenever(settings.hasShownWelcome).thenReturn(false)
whenever(settings.serverIp).thenReturn("http://127.0.0.1")
//this is where the crash happens
vm = LoginViewModel(settings, service, app, TestLog, TestDispatchers) { p -> permissionGranted }
}
下面是被测试的代码:
class LoginViewModel(private val settings: ISettings, private val service: AppService, application: Application, l: ILog, dispatchers: IDispatchers, val permissionChecker: (String) -> Boolean) : BaseViewModel(application, l, dispatchers)
val stepAdapter :StepAdapter
init {
val maxSteps = calculateSteps()
//after this assignment, during the normal run, the stepAdapter.mObservable.mObservers is an empty array
//during unit tests, after this assignment it is null
stepAdapter = StepAdapter(maxSteps)
}
【问题讨论】:
-
你的意思是android单元测试?不,不是,它是一个普通的单元测试,junit 测试,或者它们被称为
-
这个问题根本没有任何测试,虽然它可能是一个仪器测试。
-
我现在添加了显示此行为的测试的确切部分
-
Viewmodels 应该为我们提供标准化,但您的构造函数中的参数比构造函数所需的要多,并且持有对视图的引用,适配器应该在视图中,并且视图模型应该将数据转发给它.此外,测试适配器通常使用 Espresso 完成,测试 http 请求应该是 2 个不同的测试。
-
我使用了这么多参数,因为我可以访问用于设置、api 调用、协程调度程序和日志记录的接口(否则可以使用我还没有足够练习的 Dagger 来完成)。我在视图模型中使用适配器,因为它们允许我更好地控制回收站中显示的内容,我可以直接添加/删除/更新项目,如果附加了它们,它们将更新各自的视图,否则它们什么也不做。使用 livedata 更新适配器意味着整个适配器总是得到更新,而不仅仅是更改
标签: android unit-testing android-recyclerview