嗨我建立一个简单的RecycleView适配器,我试图测试适配器的所有方法,但onCreateViewHolder对我来说是困难的.
@Override public NewsViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_news,parent,false); return new NewsViewHolder(v); }
我尝试使用mockito构建一个viewGroup类的模拟,并在调用getContext()时返回MockContext的间谍,但似乎是因为我返回一个MockContext,LayoutInflater.from()返回一个空指针异常.
这是我的考验
@Test public void testOnCreateViewHolder() throws Exception { ViewGroup vg = mock(ViewGroup.class); MockContext mockContext = new MockContext(); MockContext spyContext = spy(mockContext); when(vg.getContext()).thenReturn(spyContext); NewsViewHolder vh = adapter.onCreateViewHolder(vg,0); Assert.assertNotNull("Response cant be null",vh); }
提前致谢.
解决方法
当我遇到同样的问题时,我遇到了这个问题.我最终自己解决了这个问题.
假设您有一个简单的onCreateViewHolder,如下所示:
@Override public TeamsViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { return new NewsViewHolder(LayoutInflater .from(parent.getContext()) .inflate(R.layout.fragment_news_view_holder,false) ); }
使用PowerMock模拟LayoutInflater的静态实例.在下面的代码段中,我使用编号注释注释了为使这项工作需要采取的所有步骤:
import android.test.mock.MockContext; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; // 1. signal JUnit to run this test PowerMockRunner @RunWith(PowerMockRunner.class) // 2. signal PowerMock to prepare the static instance of LayoutInflater for testing @PrepareForTest({LayoutInflater.class}) public class NewsRecyclerViewAdapterTest { // 3. LayoutInflater.from(context) returns an inflater,// so we need to mock that one @Mock LayoutInflater mockInflater; @Mock View mockView; @Mock ViewGroup mockParent; private int dummyTestId; private MockContext mockContext; private NewsRecyclerViewAdapter adapter; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); dummyTestId = 0x10000; // 4. mock the static LayoutInflater in "LayoutInflater.from()" // so that we can ask it to return a mockInflater that we moked above mockStatic(LayoutInflater.class); mockContext = new MockContext(); adapter = new NewsRecyclerViewAdapter(Arrays.asList(new NewsItem(),new NewsItem(),new NewsItem())); } @Test public void onCreateViewHolderShouldReturnAValidViewHolder() throws Exception { // 5. mock the context that comes from parent ViewGroup when(mockParent.getContext()).thenReturn(mockContext); // 6. mock the inflater that is returned by LayoutInflater.from() when(LayoutInflater.from(mockContext)).thenReturn(mockInflater); // 7. pass anyInt() as a resource id to care of R.layout.fragment_news_view_holder in onCreateViewHolder() when(mockInflater.inflate(anyInt(),eq(mockParent),eq(false))).thenReturn(mockView); // call onCreateViewHolder() to act NewsViewHolder viewHolder = adapter.onCreateViewHolder(mockParent,dummyTestId); // OKAY straightfoward right? assertNotNull(viewHolder); // this is not very important but I recommend it,// it just returns the view sent to NewsViewHolder // and verify it against the mockView that you inflated above assertEquals(viewHolder.getItemView(),mockView); } }