What is an easy way to stub / dummy a restful web service?
Asked Answered
J

5

30

I want to create an android application, this application will make RESTful calls to a web service to obtain some data.

I know what the RESTful interface will be, but I don't want the hassle of creating my own implementation. Is there an easy way to create a stub RESTful web service that will return some static data without having to write a full blown WS application to do this?

Jermainejerman answered 9/1, 2012 at 13:8 Comment(3)
do u have your own server for creating a simple mock up webservice? which language do u prefer?Fuji
I don't have my own server, but nothing stopping me from setting up tomcat for example. Since I'm dealing with android, the obvious choice would be JavaJermainejerman
if you are going to setup a server, you could create a simple static webservice within an hour.Fuji
H
0

Probably the best thing to do is create a mock for the REST web service service while you're developing your application code and then replace it with code to call the actual web service returning "real" data, once your application is written.

I'm currently writing a very similar application to yours which (like you) obtains data from a RESTful web application. In my application, I'm following the MVP pattern recommended by GWT and is also documented by Martin Fowler as the PassiveView pattern.

What you want to do is abstract away the code to make the REST web service call into an interface (the Model). The responsibility of this model class is to provide data to the Presenter/Controller. The Presenter will handle all of your business logic and then pass data up to the view (the view should be pretty dumb as well allowing it to also be mocked out). During testing, you will create a MockModel to implement the model interface and pass test data to the Presenter - without making an actual web service call at all! Then, when you're ready, you will replace this class with the actual web service and start your integration testing.

This approach has the added benefit in that it will be easy to create specific (and repeatable) test cases in your mock model. If you don't have control of the actual web service (and I'm assuming you don't), this can be difficult (or even to impossible) to achieve. The result should be a more robust, better tested application without to need to create any test XML or JSON or creating the web services yourself.

Hangnail answered 9/1, 2012 at 13:53 Comment(2)
Thats what I want to do, create a mock for ease and speed of developing the app itself. My question is, what can I use to quickly and easily build that mock?Jermainejerman
@James - I've updated my answer with more details on how I'm doing this.Hangnail
G
9

I've found using Sinatra really useful for this sort of thing if you want to test the actual HTTP calling code. You can have a endpoint returning data in seconds. Very little Ruby knowledge required.

require 'sinatra'
require 'json'

get '/Person' do
    content_type :json
    { :id => 345, :key2 => 'John Doe' }.to_json
end

Is all you would need to return a simple json object.

Gunthar answered 2/3, 2012 at 15:48 Comment(0)
F
6

One of the approaches (similar to Vinnie's) is to make a local implementation of your webservice. For example, your webservice allows you to log a user in and to get a list of users online.

The webservice interface looks like this:

public interface WebService {
    public LoginResponse login(String user, String pass) throws Exception;
    public UsersOnlineResponse getOnlineUsers() throws Exception;
}

Then, we implement this interface for remote webservice which will be used in production. Remote implementation makes HTTP calls with help of HTTP client, retrieves response and parses it to an appropriate response object. Here is a fragment of it:

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;
    }
}

For testing purposes, when webservice is not available or is being developed, we implement local webservice. Local implementation takes predefined JSON responses from assets folder and parses it to an appropriate response object. It's up to you how to implement webservice behaviour: it can be simple static responses or some random/validation-dependent responses. Here is the part of it:

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);
    }
}

Next, we want to switch between implementations painlessly. The usage of both implementations of the webservice is transparent, because we use WebService interface. So, we'll configure the WebService instance on app launch. Application class suits our needs:

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();
    }
}
Fortitude answered 6/3, 2013 at 9:12 Comment(0)
V
1

I ended up writing a mock service tool for a similar purpose: https://github.com/clafonta/Mockey/wiki

A mock service is a great tool for quickly building UIs and validating your client code, but it can become a rabbit hole, so I recommend you use something that is already out there before building your own. Github has plenty of results when you search for 'mock'. Regardless of what you do, here are a few key stumbling blocks that you may encounter.

  • You end up working with the wrong data/JSON format. For example, your app works great with the mock service, but breaks when hitting the real service because your app consumes a JSON object but the real service returns an Array of JSON objects. To avoid this, you could try using JSON Schema to help highlight invalid JSON models in your mock service.

  • Your app doesn't make a valid request. Your mock service will typically not care about the incoming request. For example, the real service needs a "customerID" and your app never passes it in. To avoid this, you could build some "required request parameter" validation logic in your mock service.

  • Testing challenges. Your automated functional testing approach needs to interact with your mock service tool if you want to test things beyond the simple "happy path". For example, you run your test "user A logs-in and sees 0 messages" vs. "user B logs-in and sees 20 messages".

Veronica answered 18/3, 2013 at 15:54 Comment(0)
H
0

Probably the best thing to do is create a mock for the REST web service service while you're developing your application code and then replace it with code to call the actual web service returning "real" data, once your application is written.

I'm currently writing a very similar application to yours which (like you) obtains data from a RESTful web application. In my application, I'm following the MVP pattern recommended by GWT and is also documented by Martin Fowler as the PassiveView pattern.

What you want to do is abstract away the code to make the REST web service call into an interface (the Model). The responsibility of this model class is to provide data to the Presenter/Controller. The Presenter will handle all of your business logic and then pass data up to the view (the view should be pretty dumb as well allowing it to also be mocked out). During testing, you will create a MockModel to implement the model interface and pass test data to the Presenter - without making an actual web service call at all! Then, when you're ready, you will replace this class with the actual web service and start your integration testing.

This approach has the added benefit in that it will be easy to create specific (and repeatable) test cases in your mock model. If you don't have control of the actual web service (and I'm assuming you don't), this can be difficult (or even to impossible) to achieve. The result should be a more robust, better tested application without to need to create any test XML or JSON or creating the web services yourself.

Hangnail answered 9/1, 2012 at 13:53 Comment(2)
Thats what I want to do, create a mock for ease and speed of developing the app itself. My question is, what can I use to quickly and easily build that mock?Jermainejerman
@James - I've updated my answer with more details on how I'm doing this.Hangnail
C
0

Create some files with dummy responses and put into a folder. Now go to command-line and execute the following: python -m SimpleHTTPServer

You can now access these files and dummy responses at http://:8000

Chromonema answered 9/7, 2014 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.