Android 单元测试中使用Robolectric的模拟RESTAPI调用

Android 单元测试中使用Robolectric的模拟RESTAPI调用,android,unit-testing,android-fragments,robolectric,spring-android,Android,Unit Testing,Android Fragments,Robolectric,Spring Android,大家好,我在单元测试中使用Robolectric、Mockito和Mockito,我需要验证依赖于api请求调用的数据 如何编写代码,以便在运行单元测试时RESTAPI调用将使用模拟数据 在StockFragment.java中,我使用SpringAndroid+Robospice执行RESTAPI调用。 另外,我在片段中有一个来自Robospice的RequestListener,如果请求成功与否,它会更新片段中的UI 这是我的片段: public class StockFragment

大家好,我在单元测试中使用Robolectric、Mockito和Mockito,我需要验证依赖于api请求调用的数据

如何编写代码,以便在运行单元测试时RESTAPI调用将使用模拟数据

在StockFragment.java中,我使用SpringAndroid+Robospice执行RESTAPI调用。 另外,我在片段中有一个来自Robospice的RequestListener,如果请求成功与否,它会更新片段中的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 ...
        }
    }
}
我正在考虑的一个解决方案是在StockFragment中使用testMode标志,并执行一些条件语句,如果为true,这些语句将返回测试数据,但我认为有一种更好的测试方法。 我想我需要在我的测试类上监听Http请求并捕获该请求,然后提供模拟数据,不过我不确定。 注:Robolectric已设置,并已确认正常工作和测试。虽然我没有在上面的代码片段中包含它们。
Roboguice也被用作注入。

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

我还鼓励您从视图中删除网络逻辑。让它保持活跃

此外,我还可以选择性地隐藏关于特定网络框架(RoboSpice)使用的概念

至于现在,您可以通过下一步修复测试

使用Robolectric运行测试:

@RunWith( RobolectricTestRunner.class )
@Config( reportSdk = 18, emulateSdk = 18 )
public class StockFragmentTest {...}
为SpiceManager添加模拟:

创建测试活动:

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> );
    ...
}
使用测试活动:

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> );
    ...
}

我认为最后一段代码不适用于您的代码。你可能有股票交易。因此,您应该通过类比来创建TestStockActivity,并替换BaseTestActivity的用法。然而,我预计这种方法会产生更多的副作用。适当的依赖注入将有助于

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


详细信息和示例可在

的答案中找到,我将避免修改代码以了解测试存在性这也将因ClassCastException而失败,因为FragmentTestUtil将尝试将片段附加到活动实例,而不是BaseActivity,但在此之前,它将因StubException而失败,因为您需要使用RobolectrictTestRunneRobolectric设置正确,不会因异常而失败,我只是没有将其包含在上面的代码中。对于ClassCastException,你的建议是什么?嗨,尤金,你是对的ClassCastException发生了。我用Roboguice打针。您能否提供包含更多详细信息或教程的资源/文章的链接?这个概念对我来说仍然太宽泛了。下面是如何将RoboGuice与片段一起使用:下面是如何进行POJO注入:下面是如何定义绑定:下面是如何在测试中覆盖注入: