万一您的活动,片段和UI需要进行一些后台处理,则最好使用MockWebServer,该MockWebServer在android设备上本地运行,为您的UI带来封闭且可测试的环境。
https://github.com/square/okhttp/tree/master/mockwebserver
第一步是包括gradle依赖项:
testCompile 'com.squareup.okhttp3:mockwebserver:(insert latest version)'
现在,运行和使用模拟服务器的步骤是:
创建模拟服务器对象
从特定的地址和端口(通常是localhost:portnumber)启动它
排队响应特定请求
开始测试
在mockwebserver的github页面上对此进行了很好的解释,但是在我们的例子中,我们希望对所有测试都可以使用更好和可重用的东西,并且JUnit规则将在这里发挥作用:
/**
*JUnit rule that starts and stops a mock web server for test runner
*/
public class MockServerRule extends UiThreadTestRule {
private MockWebServer mServer;
public static final int MOCK_WEBSERVER_PORT = 8000;
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
startServer();
try {
base.evaluate();
} finally {
stopServer();
}
}
};
}
/**
* Returns the started web server instance
*
* @return mock server
*/
public MockWebServer server() {
return mServer;
}
public void startServer() throws IOException, NoSuchAlgorithmException {
mServer = new MockWebServer();
try {
mServer(MOCK_WEBSERVER_PORT);
} catch (IOException e) {
throw new IllegalStateException(e,"mock server start issue");
}
}
public void stopServer() {
try {
mServer.shutdown();
} catch (IOException e) {
Timber.e(e, "mock server shutdown error”);
}
}
}现在,我们假设我们具有与上一个示例完全相同的活动,只是在这种情况下,当我们按下按钮应用程序时,将从网络上获取某些内容,例如:https://someapi.com/name
这将返回一些文本字符串,这些文本字符串将在快餐栏文本(例如,NAME +您输入的文本)中串联在一起。
/**
* Testing of the snackbar activity with networking.
**/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SnackbarActivityTest{
//意式咖啡规则,告诉您要开始哪个活动
@Rule
public final ActivityTestRule<SnackbarActivity> mActivityRule =
new ActivityTestRule<>(SnackbarActivity.class, true, false);
//启动模拟Web服务器
@Rule
public final MockServerRule mMockServerRule = new MockServerRule();
@Override
public void tearDown() throws Exception {
//与前面的示例相同
}
@Override
public void setUp() throws Exception {
//与前面的示例相同
**//重要提示:**将您的应用程序指向您的模拟网络服务器端点,例如
MyAppConfig.setEndpointURL("http://localhost:8000");
}
/**
*Test methods should always start with "testXYZ" and it is a good idea to
*name them after the intent what you want to test
**/
@Test
public void testSnackbarIsShown() {
//设置模拟网络服务器
mMockServerRule.server().setDispatcher(getDispatcher());
mActivityRule.launchActivity(null);
//检查是否显示了我们的文本输入并在其中输入一些文本
String textToType="new snackbar text";
onView(withId(R.id.textEntry)).check(matches(isDisplayed()));
//我们检查的是我们的快餐栏,显示来自模拟Web服务器的文本以及我们键入的文本
onView(withId(R.id.textEntry)).perform(typeText("JazzJackTheRabbit" + textToType));
//点击按钮显示小吃栏
onView(withId(R.id.shownSnackbarBtn)).perform(click());
//断言显示了带有带有我们键入并显示的文本的snackbar_id的视图
onView(allOf(withId(android.support.design.R.id.snackbar_text),
withText(textToType))) .check(matches(isDisplayed()));
}
/**
*creates a mock web server dispatcher with prerecorded requests and responses
**/
private Dispatcher getDispatcher() {
final Dispatcher dispatcher = new Dispatcher() {
@Override
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
if (request.getPath().equals("/name")){
return new MockResponse().setResponseCode(200)
.setBody("JazzJackTheRabbit");
}
throw new IllegalStateException("没有设置模拟 " + request.getPath());
}
};
return dispatcher;
}我建议将调度程序包装在某种构建器中,以便您可以轻松地链接屏幕并为屏幕添加新的响应。例如
return newDispatcherBuilder()
.withSerializedJSONBody("/authenticate", Mocks.getAuthenticationResponse())
.withSerializedJSONBody("/getUserInfo", Mocks.getUserInfo())
.withSerializedJSONBody("/checkNotBot", Mocks.checkNotBot());