什么是存根/虚拟宁静的Web服务的简单方法?

Jim*_*mmy 27 rest android web-services stub dummy-data

我想创建一个Android应用程序,这个应用程序将对Web服务进行RESTful调用以获取一些数据.

我知道RESTful接口会是什么,但我不想要创建自己的实现的麻烦.有没有一种简单的方法来创建一个存根RESTful Web服务,它将返回一些静态数据而无需编写完整的WS应用程序来执行此操作?

Joh*_*han 14

Mocky.io允许您创建存根端点并指定它们通过公共URL返回的数据.

Runscope(免责声明,我是创始人)允许您捕获一次真实请求,然后根据需要通过响应回放 URL 重播响应.


bre*_*ust 9

如果你想测试实际的HTTP调用代码,我发现使用Sinatra对这类事情非常有用.您可以让端点在几秒钟内返回数据.需要很少的Ruby知识.

require 'sinatra'
require 'json'

get '/Person' do
    content_type :json
    { :id => 345, :key2 => 'John Doe' }.to_json
end
Run Code Online (Sandbox Code Playgroud)

你只需要返回一个简单的json对象.


vok*_*lam 6

其中一种方法(类似于Vinnie)是在本地实现您的Web服务.例如,您的Web服务允许您在线登录用户并获取用户列表.

webservice接口如下所示:

public interface WebService {
    public LoginResponse login(String user, String pass) throws Exception;
    public UsersOnlineResponse getOnlineUsers() throws Exception;
}
Run Code Online (Sandbox Code Playgroud)

然后,我们为将在生产中使用的远程web服务实现此接口.远程实现在HTTP客户端的帮助下进行HTTP调用,检索响应并将其解析为适当的响应对象.这是它的一个片段:

public class RemoteWebService implements WebService {
    private AndroidHttpClient client = AndroidHttpClient.newInstance(USER_AGENT);

    @Override
    public LoginResponse login(String user, String pass) throws Exception {
        LoginResponse response = client.execute(
            createPostRequest(METHOD_LOGIN, user, pass), 
            new JsonResponseHandler(LoginResponse.class));

        handleResponse(response); // verify response, throw exceptions if needed
        return response;
    }
}
Run Code Online (Sandbox Code Playgroud)

出于测试目的,当webservice不可用或正在开发时,我们实现本地Web服务.本地实现从assets文件夹获取预定义的JSON响应,并将其解析为适当的响应对象.由您决定如何实现Web服务行为:它可以是简单的静态响应或一些随机/验证相关的响应.这是它的一部分:

public class LocalWebService implements WebService {
    private Context context;

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

    @Override
    public LoginResponse login(String user, String pass) throws Exception {
        Thread.sleep(DELAY); //emulate network delay

        if (validateParams(user, pass)) {
            return parseAssetsJson("ws/login.json", LoginResponse.class);
        } else {
            Response response = parseAssetsJson("ws/status_bad_request.json", Response.class);
            throw new WebServiceException(response);
        }
    }

    public <T> T parseAssetsJson(String filename, Class<T> klass) throws IOException {
        InputStream is = context.getAssets().open(filename);
        return JsonParser.getInstance().fromJson(new InputStreamReader(is), klass);
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,我们希望无痛地在实现之间切换.webservice的两种实现的使用都是透明的,因为我们使用WebService接口.因此,我们将在应用程序启动时配置WebService实例.应用类适合我们的需求:

public class App extends Application {
    public static final boolean USE_LOCAL_WS = false;
    private static WebService webService;

    public static getWebService() {
        return webService;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        webService = USE_LOCAL_WS ? new LocalWebService(this) : new RemoteWebService();
    }
}
Run Code Online (Sandbox Code Playgroud)


Vin*_*nie 0

最好的办法可能是在开发应用程序代码时为 REST Web 服务创建一个模拟,然后在编写应用程序后将其替换为代码以调用返回“真实”数据的实际 Web 服务。

我目前正在编写一个与您的应用程序非常相似的应用程序,它(像您一样)从 RESTful Web 应用程序获取数据。在我的应用程序中,我遵循GWT 推荐的MVP模式,并且 Martin Fowler 也将其记录为PassiveView模式。

您想要做的是将 REST Web 服务调用的代码抽象为接口(模型)。该模型类的职责是向 Presenter/Controller 提供数据。Presenter 将处理您的所有业务逻辑,然后将数据传递到视图(视图应该非常愚蠢,也允许它被模拟)。在测试期间,您将创建一个 MockModel 来实现模型接口并将测试数据传递给 Presenter - 根本不需要进行实际的 Web 服务调用!然后,当您准备好时,您将用实际的 Web 服务替换此类并开始集成测试。

这种方法还有一个额外的好处,那就是可以轻松地在模拟模型中创建特定的(且可重复的)测试用例。如果您无法控制实际的 Web 服务(我假设您没有),那么这可能很难(甚至不可能)实现。结果应该是一个更健壮、经过更好测试的应用程序,而无需创建任何测试 XML 或 JSON 或自行创建 Web 服务。