Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Espresso用户界面测试,模拟改型API_Android_Api_Retrofit_Android Espresso_Ui Testing - Fatal编程技术网

Android Espresso用户界面测试,模拟改型API

Android Espresso用户界面测试,模拟改型API,android,api,retrofit,android-espresso,ui-testing,Android,Api,Retrofit,Android Espresso,Ui Testing,我正在使用Espresso为我的Android应用程序创建UI测试 我有一个登录屏幕,其中只包含两个字段(用户和密码)和一个按钮 我正在使用reformation但是我想模拟API响应,所以我创建了一个reformationmockclient 例如,在下一个测试中我故意键入错误的密码,以检查是否显示错误消息 @Test public void loginFailed() { onView(withId(R.id.login_user_name)).perform(typeText("m

我正在使用
Espresso
为我的
Android
应用程序创建
UI测试

我有一个
登录
屏幕,其中只包含两个
字段
(用户和密码)和一个
按钮

我正在使用
reformation
但是我想模拟
API
响应,所以我创建了一个
reformationmockclient

例如,在下一个
测试中
我故意键入错误的
密码
,以检查是否显示
错误
消息

@Test
public void loginFailed() {
    onView(withId(R.id.login_user_name)).perform(typeText("myUser"));
    onView(withId(R.id.login_user_password)).perform(typeText("wrongPassword"), closeSoftKeyboard());

    onView(withId(R.id.login_button)).perform(click());

    // Failed login shows error message.
    onView(withText(R.string.login_error_message)).check(matches(isDisplayed()));
}
问题是,当执行单击时,会触发一个
改装
API
调用,即我想要模拟的调用

有什么想法吗?我还对
UI测试
/
单元测试
以及这个
测试
是否合理感到困惑。我只想检查
登录过程中
API
返回
错误时是否显示
错误消息

提前谢谢

编辑:

我已经按照用户
fzxt
的建议,使用 示例中提供的
RestServiceTestHelper

现在我的
测试
如下所示:

@RunWith(AndroidJUnit4.class)
public class LoginUIAndroidTest {

    private static MockWebServer mockWebServer;


    @Rule
    public ActivityTestRule<LoginActivity> mActivityRule = new IntentsTestRule<>(LoginActivity.class,
            true,    // initialTouchMode
            false); // launchActivity - false so we could customize the intent




    @BeforeClass
    public static void startMockServer() throws Exception {
        mockWebServer = new MockWebServer();
        mockWebServer.start();
        mockWebServer.url("/");
    }


    @AfterClass
    public static void shutdownMockServer() throws Exception {
        mockWebServer.shutdown();
    }
    @Test
    public void testLoginSuccess() throws Exception {

        String fileName = "quote_login_200_ok.json";
        mockWebServer.enqueue(new MockResponse()
                .setResponseCode(200)
                .setBody(RestServiceTestHelper.getStringFromFile(getInstrumentation().getContext(), fileName)));


        onView(withId(R.id.login_user_name)).perform(typeText("user"));
        onView(withId(R.id.login_user_password)).perform(typeText("password"), closeSoftKeyboard());

        onView(withId(R.id.login_button)).perform(click());

        // Successful login moves user to next screen.
        intended(hasComponent(new ComponentName(getInstrumentation().getTargetContext(), ProjekteActivity.class)));
    }
这是我的
后勤活动

 public class LoginActivity extends Activity {

        ...

        @OnClick(R.id.login_button)
        public void loginUser(final View view) {
            final MyRetrofitService service = createRetrofitService();

            service.login(new AuthenticationLoginDTO(email, password, deviceUUID), new Callback < AuthenticationDTO > () {
                @Override
                public void success(final AuthenticationDTO authenticationDTO, final Response response) {}

                @Override
                public void failure(final RetrofitError retrofitError) {}
            });

        }



        protected MyRetrofitService createRetrofitService() {
            final RequestInterceptor requestInterceptor = new RequestInterceptor() {
                @Override
                public void intercept(final RequestInterceptor.RequestFacade request) {
                    request.addHeader(getString(R.string.header_api_key), getString(R.string.api_key));
                    request.addHeader(getString(R.string.header_context), getString(R.string.context));
                }
            };
            final Gson dateTimeConverter = new GsonBuilder()
                .registerTypeAdapter(DateTime.class, new DateTimeConverter())
                .create();
            final RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("/")
                .setConverter(new GsonConverter(dateTimeConverter))
                .setRequestInterceptor(requestInterceptor)
                .setExecutors(AsyncTask.THREAD_POOL_EXECUTOR, new MainThreadExecutor())
                .setLogLevel(RestAdapter.LogLevel.FULL).setLog(new AndroidLog(Config.TAG))
                .build();
            return restAdapter.create(MyRetrofitService.class);
        }
    }
我遗漏了一些东西,因为当
Espresso
执行
单击
操作时,将调用真正的
Api
,而不是
MockWebServer

onView(withId(R.id.login_button)).perform(click());
我见过一些使用
dagger2
改型2.0
的例子,但不幸的是,我现在不得不使用
改型1.9


提前谢谢。

您可以试试。感谢您的回答@fzxt,我已经在您的活动中更新了我的问题,您是否已将其设置为它实际将请求发送到“/”?如果只是ping实际的服务器,那么你的MockWebServer将永远不会被使用。你是说这行吗<代码>mockWebServer.url(“/”)我是指您的实际活动代码。这里当前发生的事情是,您启动一个Web服务器,输入用户、密码并单击login,这将调用您的loginactivitys onClick listener来获取该按钮。你可以用两种方法来解决这个问题,一种是你可以更改你的loginactivity onclick listener,以便它将请求发送到mockwebserver。第二,您可以使用和,以便当您的loginactivity调用方法ping您的Web服务器时,您可以模拟响应。
public interface NGOPService {

    String AUTHENTICATION_ENDPOINT = "";

    @POST(AUTHENTICATION_ENDPOINT)
    void login(@Body AuthenticationLoginDTO authRequest, Callback < AuthenticationDTO > callback);

}
onView(withId(R.id.login_button)).perform(click());