为什么在Mockito测试期间源代码另有说明时,受保护的最终字段为空?

时间:2016-10-29 15:29:48

标签: java android junit android-recyclerview mockito

我使用Mockito 1.10.19创建测试来测试自定义RecyclerView适配器。 (代码已经过简化以消除信息噪音,留下最简单的版本仍有问题)

public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {

    private final Dependency dependency;

    public CustomAdapter(@NonNull Dependency dependency) {
        this.dependency = dependency;
    }

    public void refreshData() {
        dependency.refreshData();
        notifyDataSetChanged();
    }

    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.ingredients_item, parent, false);
        return new CustomViewHolder(view);
    }

    @Override
    public void onBindViewHolder(CustomViewHolder holder, int position) {
        dependency.bind(holder, position);
    }

    @Override
    public int getItemCount() {
        return dependency.getItemsCount();
    }
}

我已经为它注入了模拟的依赖项,但是适配器却没有被触及。

@RunWith(MockitoJUnitRunner.class)
public class CustomAdapterTest {

    private CustomAdapter adapter;
    @Mock
    private Dependecy dependencyMock;

    @Before
    public void setUp() throws Exception {
        adapter = new CustomAdapter(dependencyMock);
    }

    @Test
    public void testRefreshData() throws Exception {
        adapter.refreshData();
        verify(dependencyMock).refreshData();
        verifyNoMoreInteractions(dependencyMock);
    }
}

运行非常简单的测试&#39; testRefreshData()&#39;适配器调用notifyDataSetChanged()。这会导致NullPointerException被抛出。

在android.support.v7.widget.RecyclerView $ AdapterDataObservable.notifyChanged(RecyclerView.java:10763) 在android.support.v7.widget.RecyclerView $ Adapter.notifyDataSetChanged(RecyclerView.java:6342)

这在代码中发生:

static class AdapterDataObservable extends Observable<AdapterDataObserver> {
    public boolean hasObservers() {
        return !mObservers.isEmpty();
    }
public void notifyChanged() {
    // since onChanged() is implemented by the app, it could do anything, including
    // removing itself from {@link mObservers} - and that could cause problems if
    // an iterator is used on the ArrayList {@link mObservers}.
    // to avoid such problems, just march thru the list in the reverse order.
    for (int i = mObservers.size() - 1; i >= 0; i--) {
        mObservers.get(i).onChanged();
    }
}

derefencing mObservers时。这不应该发生,因为Observable<T>mObservers定义为final并初始化:

public abstract class Observable<T> {
    /**
     * The list of observers.  An observer can be in the list at most
     * once and will never be null.
     */
    protected final ArrayList<T> mObservers = new ArrayList<T>();

为什么会这样?这是某种错误还是已知的限制?我该如何解决这个问题? (不计算Robolectric,我决定停止使用它,因为它有自己的问题)

在有人要求之前;这只发生在测试期间,经过测试的代码工作正常。

使用的版本:JUnit 4.12。 Mockito 1.10.19,支持库25.0.0,Android Studio 2.2.2,jdk 1.8.0_112,

1 个答案:

答案 0 :(得分:4)

这可能是因为您尝试使用JUnit测试依赖于Android框架类的代码。

请阅读this answer至另一个与完全相同的问题相关的问题。