[英]Android Tests: Stubbing out Retrofit with Mockito
In my MainActivity
I have a method called getAPI
that returns an OTBServiceWrapper
. 在我的MainActivity
我有一个名为getAPI
的方法,它返回一个OTBServiceWrapper
。 This is used to setup retrofit for calling to an API. 这用于设置用于调用API的改进。
In my MainActivityTest
file I am trying to stub out the new OTBService().getService()
call that the getApi
method is making so I can return a MockedOTBService
which changes the client to a custom one that return json
. 在我的MainActivityTest
文件中,我试图找出getApi
方法正在进行的new OTBService().getService()
调用,这样我就可以返回一个MockedOTBService
,它将客户端更改为返回json
的自定义客户端。
As is, the current implementation will it the MockedOTBService
if I had to place a logger within MockedOTBService
but also falls through and calls the real api, which is not want I want in a test. MockedOTBService
如果我不得不在MockedOTBService
放置一个记录器但是它也会通过并调用真正的api,那么当前的实现将是MockedOTBService
,这在测试中不是我想要的。
I am trying to stub the Retrofit API calls using Mockito and return json
. 我试图使用Mockito存根Retrofit API调用并返回json
。 I cant seem to understand why the stub is being called yet is not stubbing the method in question. 我似乎无法理解为什么存根被调用尚未存在问题的方法。
Notes: 笔记:
ActivityInstrumentationTestCase2
我正在使用ActivityInstrumentationTestCase2
verify(mockedOTBService, atLeastOnce()).getService();
如果我添加一个verify(mockedOTBService, atLeastOnce()).getService();
is says it was never called. 据说它从未被称为。 when...thenReturn
to use a mMainActivity = spy(getActivity())
there is not change and the real API is called. 如果我更改when...thenReturn
使用mMainActivity = spy(getActivity())
则没有更改并且会调用真正的API。 Logcat Output 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 真正的流量
MainActivity.onCreate() > OTBService.getService() > OTBServiceWrapper.createSearch(...) MainActivity.onCreate()> OTBService.getService()> OTBServiceWrapper.createSearch(...)
Trying to Achieve within Tests 试图在测试中实现
MainActivity.onCreate() > MockedOTBService.getService() > OTBServiceWrapper.createSearch(...) MainActivity.onCreate()> MockedOTBService.getService()> OTBServiceWrapper.createSearch(...)
MainActivity.java 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 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 OTBServiceWrapper.java
public interface OTBServiceWrapper {
@POST(Constants.API_SEARCHES_POST_URL)
void createSearch(@Body Request request, Callback<Request.Response> callback);
}
MainActivityTest.java 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 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 LocalJsonClient.java
@SuppressLint("DefaultLocale")
public class LocalJsonClient implements Client { ... }
build.gradle 的build.gradle
dependencies {
androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
}
Remove the need for mocking your request by allowing the Activity to set the service. 通过允许Activity设置服务,无需模拟您的请求。
In your MainActivity
create a class variable and a class setter for the service. 在MainActivity
,为服务创建一个类变量和一个类设置器。 It needs to be a at the class scope to prevent the OnCreate
method being called before you have set the service to what you want it to be. 它必须是类范围,以防止在将服务设置为您希望的服务之前调用OnCreate
方法。 Also create an instance getter which sets the service if you have not already. 还要创建一个实例getter来设置服务(如果还没有)。
In your test before you call getActivity()
set the service to be your mock service. 在您调用getActivity()
之前的测试中,将服务设置为您的模拟服务。 (Maybe think about moving this out to a support object). (也许考虑将其移到支持对象)。
MainActivity.java 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 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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.