android - 在 Android 中使用虚假的 http 响应测试 Activity

标签 android testing android-async-http

我有一个用于注册的 Activity。Activity 获取用户的个人资料,如电子邮件和密码,然后将这些值上传到服务器。服务器将在成功后将这些值返回给 Activity,以便 Activity 将它们保存到 SharedPreferences。
我的问题是,如何编写一个返回假响应的测试,以便 Activity 不必与真实服务器交互,并检查值是否已准确保存到首选项中?

这是我的 Activity :

public class RegisterActivity extends AppCompatActivity implements RegisterRestClientUsage.RegisterCallback{
    private RegisterRestClientUsage registerRestClientUsage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        registerRestClientUsage = new RegisterRestClientUsage(this);
        //...
    }
    public void onClick(View view){
        String email = emailEditText.getText().toString();
        String password = passwordEditText.getText().toString();
        registerRestClientUsage.registerToServer(email,password);
    }
    @Override
    public void registerSuccess(String token, String email) {

        //Save those values to SharedPreferences

        finish();
    }

    @Override
    public void registerFail() {
        finish();
    }
}

RegisterClientUsage.class

public class RegisterRestClientUsage {
    private RegisterCallback callback;
    public interface RegisterCallback{
        void registerSuccess(String token,String email);
        void registerFail();
    }

    public RegisterRestClientUsage(RegisterCallback r){
        callback = r;
    }
    public void registerToServer(String email,String password){
            RequestParams params = new RequestParams();
            params.put("email", email);
            params.put("password", password);

            BaseRestClient.post("api/users/sign_up", params, new AsyncHttpResponseHandler() {
                @Override
                public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                    try {
                        JSONObject responseJson = new JSONObject(new String(responseBody));
                        returnToken = responseJson.optString("token");
                        JSONObject userJson = responseJson.optJSONObject("user");
                        returnEmail = userJson.optString("email");
                        callback.registerSuccess(returnToken,returnEmail);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                    callback.registerFail();
                }
            });
    }
}  

BaseRestClient.class

public class BaseRestClient {
    public static final String BASE_URL =  "https://my.api.com/";
    private static AsyncHttpClient client = new AsyncHttpClient();

    public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
        client.post(getAbsoluteUrl(url), params, responseHandler);
    }

由于 RegisterRestClientUsage 嵌入在 RegisterActivity 中,我找不到将我的假服务器注入(inject) Activity 的好方法。

最佳答案

感谢 @geek90 的帮助,我终于想出了一个解决方案。我只是用另一个 Controller (RegisterController.class)包装我真正的 api 实现(RegisterRestClientUsage.class) ):

public class RegisterController{

    private RegisterServer serverSide;

    public RegisterController(RegisterServer r){
        serverSide = r;
    }

    public void registerToServer(String email,String password) {
        RequestParams params = new RequestParams();
        params.put("email", email);
        params.put("password", password);
        serverSide.registerToServer(params);
    }
} 

RegisterRestClientUsage.class实现RegisterServer接口(interface):

public interface RegisterServer{
    void registerToServer(String email,String  pwd);
}

并且在RegisterActivityonCreate()方法中,构造带有参数RegisterRestClientUsage的 Controller

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_register);
    registerController = new RegisterController(new RegisterRestClientUsage(this));
    //...
}

在这种情况下,我可以将我伪造的 api 实现 stub 到 Controller 中进行测试:

@RunWith(AndroidJUnit4.class)
public class RegisterActivityTest {
    FakeRegisterRestClientUsage fakeRegisterRestClientUsage;
    @Rule
    public ActivityTestRule<RegisterActivity> activityTestRule = new ActivityTestRule<>(RegisterActivity.class);
    @Before
    public void setUp(){
        Activity activity = activityTestRule.getActivity();
        fakeRegisterRestClientUsage = new FakeRegisterRestClientUsage((RegisterRestClientUsage.RegisterCallback) activity);
        registerController = new RegisterController(fakeRegisterRestClientUsage);
    }
    @Test
    public void savePreferenceAfterRegistration(){
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                registerController.registerToServer("FAKE_NAME", "FAKE_BIRTH", "FAKE_EMAIL", "FAKE_GENDER", "FAKE_PWD", file);
            }
        });
        waitForActionsToComplete();

        //Assert that the data has been properly save to the preferences
    }
    public void waitForActionsToComplete(){
        CountDownLatch signal = fakeRegisterRestClientUsage.signal;
        try {
            signal.await(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

关于android - 在 Android 中使用虚假的 http 响应测试 Activity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34228015/

相关文章:

java - Android/Java 中的网络 - 如何在从服务器回调后回调到 API 类?

AsyncHttpClient 的 java.lang.NoClassDefFoundError - API 19

android - 如何保存和更新xml文件中的值?

php - 在派生类中模拟数据库

android - 如何在从 LinearLayout 中删除第二个 cardview 时向第一个 cardview 添加 Add_button,即当线性布局中要留下的子项数量是?

javascript - 测试( Mocha 、 Chai )上下文中的 "chainable"是什么意思?

java - 从不受信任的 UID 调用

java - (Android | Java) AndroidAsyncHttp (Loopj) 在继续线程之前完成 Web 请求

android - Android-L 预览版中的 AppCompat/Chromecast

android - 如何删除不使用的依赖项?