Android测试:使用Mockito模拟Retrofit调用

8
在我的MainActivity中,我有一个名为getAPI的方法,它返回一个OTBServiceWrapper。这用于设置Retrofit以调用API。
在我的MainActivityTest文件中,我试图存根getApi方法正在进行的new OTBService().getService()调用,以便我可以返回一个MockedOTBService,该服务将客户端更改为返回json的自定义客户端。
当前实现会命中MockedOTBService,如果我在MockedOTBService中放置了记录器,但也会继续调用真实的API,这不是我在测试中想要的。
我正在尝试使用Mockito存根Retrofit API调用并返回json。我似乎无法理解为什么调用存根却没有存根所涉及的方法。
注意:
  1. 我正在使用ActivityInstrumentationTestCase2
  2. 我只运行一个测试
  3. 如果我添加verify(mockedOTBService, atLeastOnce()).getService();,则会显示从未调用。
  4. 如果我更改when...thenReturn以使用mMainActivity = spy(getActivity()),则没有任何更改,并且将调用真实的API。
Logcat输出
Logger﹕ MockedOTBService was called // Mock is called
Logger﹕ Real OTBService was called // Real API is called
Logger﹕ MainActivity getAPI method class is "$Proxy1" // Mock is shown in MainActivity
Logger﹕ RealAPIResponse JSON Parsed ID: 266 // Real API response returned

Real Flow

在Real Flow中:

MainActivity.onCreate() > OTBService.getService() > OTBServiceWrapper.createSearch(...)

尝试在测试中实现的目标

在测试中尝试实现的目标是:

MainActivity.onCreate() > MockedOTBService.getService() > OTBServiceWrapper.createSearch(...)

MainActivity.java

public class MainActivity extends Activity {
  private OTBServiceWrapper serviceWrapper;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getApi().createSearch(...)
  }

  public OTBServiceWrapper getApi() {
    return new OTBService().getService();
  }
}

OTBService.java

public class OTBService {
  public OTBServiceWrapper getService() {
    RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(Constants.API_URL)
        .build();

    return restAdapter.create(OTBServiceWrapper.class);
  }
}

OTBServiceWrapper.java

public interface OTBServiceWrapper {
  @POST(Constants.API_SEARCHES_POST_URL)
  void createSearch(@Body Request request, Callback<Request.Response> callback);
}

MainActivityTest.java

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
  private OTBService mMockedOTBService;
  private MainActivity mMainActivity;
  private View mSearchButton;

  public MainActivityTest() { super(MainActivity.class); }

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    setActivityInitialTouchMode(true);

    System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());

    mMockedOTBService = mock(OTBService.class);
    when(mMockedOTBService.getService()).thenReturn(new MockedOTBService(getInstrumentation().getContext()).getService());

    mMainActivity = getActivity();

    mSearchButton = mMainActivity.findViewById(R.id.AbSearchButton);
    mYourHolidayButton = mMainActivity.findViewById(R.id.AbYourHolidayButton);
  }

  public void testButtonActions() {
    TouchUtils.clickView(this, mSearchButton);
    ...
  }
}

MockedOTBService.java

public class MockedOTBService {
  private Context context;

  public MockedOTBService(Context context) { this.context = context; }

  public OTBServiceWrapper getService() {
    RestAdapter restAdapter;

    restAdapter = new RestAdapter.Builder()
        .setClient(new LocalJsonClient(context))
        .setEndpoint(Constants.API_TEST_URL)
        .build();

    return restAdapter.create(OTBServiceWrapper.class);
  }
}

LocalJsonClient.java

@SuppressLint("DefaultLocale")
public class LocalJsonClient implements Client { ... }

build.gradle

dependencies {
    androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
    androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
}
1个回答

6

通过允许活动设置服务来消除模拟请求的必要性。

在您的MainActivity中创建一个类变量和一个类设置器以设置服务。它需要在类范围内,以防止在设置服务之前调用OnCreate方法。还要创建一个实例获取器,如果您尚未设置服务,则设置服务。

在测试之前调用getActivity()之前,将服务设置为您的模拟服务。(也许考虑将这个移出到支持对象中)。

MainActivity.java

public class MainActivity extends Activity {
  private static OTBServiceWrapper serviceWrapper;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getServiceWrapper.createSearch(...)
  }

  public OTBServiceWrapper getServiceWrapper() {
    if (serviceWrapper == null) {
      MainActivity.setServiceWrapper(new OTBService().getService());
    }

    return serviceWrapper;
  }

  public static void setServiceWrapper(OTBServiceWrapper serviceWrapper) {
    MainActivity.serviceWrapper = serviceWrapper;
  }
}

MainActivityTest.java

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
  private MainActivity mMainActivity;

  public MainActivityTest() { super(MainActivity.class); }

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    setActivityInitialTouchMode(true);

    MainActivity.setServiceWrapper(
      new MockedOTBService(getInstrumentation().getContext()).getService()
    );

    mMainActivity = getActivity();
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接