1

大家好,我在单元测试中使用RobolectricMockito和 mockito,我已经到了需要验证依赖于 api 请求调用的数据的地步。

您如何编码以便在运行单元测试时您的 Rest api 调用将使用模拟数据?

在我的 StockFragment.java 中,我使用SpringAndroid + Robospice来执行 Rest Api 调用。
此外,如果请求成功与否,我在片段中还有一个 RequestListener(来自 Robospice)会更新片段中的 UI。

这是我的片段:

   public class StockFragment extends RoboDialogFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.my_layout, container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        displayStockInfo();
    }

    private void displayStockInfo(){
        request = new MyRequest();
        request.setQuote(getStock().getSymbol());
        lastRequestCacheKey = request.createCacheKey();
        ((BaseActivity)getActivity()).getSpiceManager().execute(request, lastRequestCacheKey, DurationInMillis.ALWAYS_EXPIRED, new MyRequestListener());
    }

    private class MyRequestListener implements RequestListener<PseStocksResponse> {
        @Override
        public void onRequestFailure(SpiceException e) {
            //show toast about failure reason ...
        }
        @Override
        public void onRequestSuccess(PseStocksResponse pseStocksResponse) {
            //UPDATE UI VIEWS ...
        }
    }
}

这是我的 Robolectric 测试课程。

   public class StockFragmentTest {
    MyRequest request;
    Stock stock;
    StockFragment stockFragment;

    @Before
    public void setUp(){
        stockFragment = new StockFragment();
        FragmentTestUtil.startFragment(stockInfoFragment);
        FragmentTestUtil.startVisibleFragment(stockInfoFragment);
        findViews();
    }

    public void findViews(){
        quoteTextView = (TextView)stockInfoFragment.getView().findViewById(R.id.quoteTextView);
        nameTextView = (TextView)stockInfoFragment.getView().findViewById(R.id.nameTextView );
        ...
    }

    @Test
    public void viewShouldNotBeNull(){
        assertNotNull(quoteTextView);
        assertNotNull(nameTextView);
        ...
    }

    @Test
    public void showDisplayedInfo(){
        //TODO: Assert textview.getText() values here
    }
}

我正在考虑的一种解决方案是在StockFragment中有 testMode标志,并执行一些条件语句,如果为真,则返回测试数据,但我认为有更好的测试方法。
我想我需要在我的测试类上监听 Http 请求并捕获该请求然后提供模拟数据,但我不确定。

注意:Robolectric 已设置并已确认工作和测试。虽然我没有将它们包含在上面的代码片段中。Roboguice 也用作注射剂。

4

2 回答 2

0

我鼓励您使用依赖注入框架,例如Dagger. 可能需要很长时间才能弄清楚框架是如何工作的。看看例子。

我还鼓励您从视图中删除网络逻辑。保存在Activity.

另外(可选)我会隐藏有关特定网络框架使用的概念 - RoboSpice.

至于现在,您可以通过后续步骤修复测试。

使用 Robolectric 运行测试:

@RunWith( RobolectricTestRunner.class )
@Config( reportSdk = 18, emulateSdk = 18 )
public class StockFragmentTest {...}

添加模拟SpiceManager

...
public class StockFragmentTest 
{
    @Mock
    SpiceManager mockedSpiceManager;

    @Before
    public void setUp()
        throws Exception
    {
        MockitoAnnotations.initMocks( this );
        ...
    }
    ...
}

创建测试活动:

public class StockFragmentTest 
{
    ...
    public class TestBaseActivity extends BaseActivity 
    {
        @Override
        SpiceManager getSpiceManager() 
        {
            return mockedSpiceManager;
        }
    }
}

使用测试活动:

@Before
public void setUp()
{
    ...
    stockFragment = new StockFragment();
    FragmentTestUtil.startVisibleFragment( stockFragment, TestBaseActivity.class, <id of placeholder in xml for BaseActivity> );
    ...
}

我认为最后一个片段不适用于您的代码。你可能有StockActivity. 所以你应该TestStockActivity类推并替换BaseTestActivity. 但是,我预计这种方法会产生更多副作用。正确的依赖注入将有所帮助

于 2015-02-04T11:07:23.003 回答
0

Robolectric 已经包含一个伪造的 http 层,您可以在其中准备答案。

详细信息和示例可以在 Android http testing with Robolectric的答案中找到

于 2015-02-10T07:12:23.717 回答