5. Testing your web services

The fastest way to see your web service in action is to use the web service scaffolding.

It works in the same way as Active Record’s scaffolding.

In your web services controller, use the #web_service_scaffold method to generate the actions used for performing method invocations.

Example:


  class XmlrpcController < ApplicationController
    web_service_dispatching_mode :layered
    web_service_scaffold :invoke

    web_service :metaWeblog, MetaWeblogService.new
    web_service :blogger, BloggerService.new
  end

For this example, we now have an action named invoke on the XmlrpcController.

Going to /xmlrpc/invoke in a web browser will present us with a list of methods in all the APIs attached to the controller.

We can then select a method, provide its parameters, select the invocation protocol to use, and view the results (Ruby, and XML) of the invocation request.

ActionWebService integrates with the Rails functional testing framework, so you can use the same testing idioms to ensure your APIs are working correctly.

When using the generator to create your API stubs, a skeleton functional test will be created for you in test/functional/service_name_api_test.rb.

Its pretty simple to create your own tests though.

Here’s an example test for the standard direct controller:


  require File.dirname(__FILE__) + '/../test_helper'
  require 'user_controller'

  class UserController; def rescue_action(e) raise e end; end

  class UserControllerApiTest < Test::Unit::TestCase
    def setup
      @controller = UserController.new
      @request    = ActionController::TestRequest.new
      @response   = ActionController::TestResponse.new
    end

    def test_add
      result = invoke :add, "ljb", "bitserf@gmail.com" 
      assert_equal true, result
    end
  end

This tests an add web services method defined UserController. It does a complete Action Pack request/response, to emulate how your API will be invoked.

The name you use as first parameter to #invoke should be the same as the name you used in the API definition. All parameters after the name are method parameters.

The return value of #invoke will be the return value of the invoked method.

Testing Delegated/Layered API methods

The above example is fine if you want to test an API implemented directly in the controller. However, if you have a delegated or layered service implementation, you should use either #invoke_layered or #invoke_delegated to test your APIs (both accept the same parameter list).

Example:


  require File.dirname(__FILE__) + '/../test_helper'
  require 'xmlrpc_controller'

  class XmlrpcController; def rescue_action(e) raise e end;     
  end

  class XmlrpcApiTest < Test::Unit::TestCase
    def setup
      @controller = XmlrpcController.new
      @request    = ActionController::TestRequest.new
      @response   = ActionController::TestResponse.new
    end

    def test_new_post
      args = []
      result = invoke_layered, :metaWeblog, :newPost, *args
      assert_equal "1", result
    end
  end

To test with third party clients, you need to know what the endpoint URL for your web services is going to be.

For direct, and layered dispatching, the endpoint URL is:

http://SERVER/CONTROLLER_NAME/api

For delegated dispatching, the endpoint URL is:

http://SERVER/CONTROLLER_NAME/SERVICE_NAME

Explanation

Having two different URLs for these difference cases may seem arbitrary, but there is a reason:

For delegated and layered dispatching, we receive the information telling us which service object the invocation should be routed to, in the message or HTTP headers.

For delegated dispatching, we have no such guarantee, and thus, rely on the action name to determine which service it should go to.