3

Hello folks, I wrote a low level implementation for a XmlRPC-Api and I've trouble to test the communication.

Here is my code.

abstract class BaseClient
{
    protected function call($method, array $params = array())
    {
        $request = xmlrpc_encode_request($method, $parameters);

        $file = file_get_contents($this->getDSN(), false, $context);
        $response = xmlrpc_decode($file);

        if ($response && xmlrpc_is_fault(array($response))) {
            trigger_error("xmlrpc: {$response[faultString]} ({$response[faultCode]})");
        }

        return $response;
    }
}


Client extends BaseClient
{
    public function testCall($msg)
    {
        return $this->call('testMethid', array($msg));
    }
}

And here is my Test.

ClientTest extends PHPUnit_FrameWork_TestCase
{
    public function testTestCall()
    {
        $c = new Client();
        $resp = $c->testCall('Hello World');

        $this->assertEquals('Hello World', $resp);
    }
}

This test will crash every time, because its not possible to access the api inside a testing environment. I can't see a solution to mock and inject the call function. What can I do? Maybe my object structure is bad and not able to test and how can I improve this structure (if this happen)?

Cheers.

3
  • If the API is not accessible then what are you actually testing? Commented Aug 15, 2013 at 14:12
  • Yep, the api is NOT accessible in my testing environment. Commented Aug 15, 2013 at 14:14
  • So my point is, what's left to actually test, given that the API is not there? The whole point of the call() method is to call the API, so how can you test it if the API isn't there? Commented Aug 15, 2013 at 14:16

2 Answers 2

2

Since you're trying to test an external API, I would begin by wrapping your file_get_contents() call in another class and injecting that into your BaseClient. In the simplest form, it might look something like this:

class RemoteFileRetriever
{
    public function retrieveFileContents($url)
    {
        // Do some work to create $context
        ...

        // Now grab the file contents
        $contents = file_get_contents($url, false, $context);

        return $contents;
    }
}

abstract class BaseClient
{
    private $fileRetriever;

    public function __construct(RemoteFileRetriever $fileRetriever)
    {
        $this->fileRetriever = $fileRetriever;
    }

    protected function call($method, array $params = array())
    {
        ...

        $file = $this->fileRetriever->retrieveFileContents($this->getDSN());

        ...
    }
}

Now in your test, you can use a mock object to inject as the file retriever. E.g.:

class ClientTest extends PHPUnit_FrameWork_TestCase
{
    public function testTestCall()
    {
        $mockRetriever = new MockRemoteFileRetriever();
        $c = new Client($mockRetriever);
        $resp = $c->testCall('Hello World');

        $this->assertEquals('Hello World', $resp);
    }
}

PHPUnit atually has some built-in helpers for mocking. See PHPUnit's Mock Objects.

Sign up to request clarification or add additional context in comments.

Comments

0

You don't want to mock the call function.

If you can't setup a fake service then you want to mock the php functions which you can do using PHP Namespacing (Have to have PHP 5.3). You can then create mocks for internal php functions that you are calling in your call method.

http://www.schmengler-se.de/-php-mocking-built-in-functions-like-time-in-unit-tests

If you are not able to do this, testing can be pretty difficult. Can you create a fake api that you can hit for testing? Remember that you aren't actually testing the methods of the api, rather you are trying to make sure that you code makes the request to the api and handles the response in the manner you intend.

As a rule, assume that third party code has been tested and works properly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.