views:

48

answers:

1

Hi,

I'm trying to write some unit tests for a class that connects to an API.

What I want to do is alter the class so that instead of actually connecting to the API, it instead loads a pre-fetched constant fixture. The method within the class that actually does the cURL request and returns the data is protected, and this is the one I want to change to instead return the contents of the fixture file.

My question is what's the best way to do this?

I've read about mock objects in PHPUnit, but because the method I want to change is internal and protected, I don't think I can use those right?

Am I correct in assuming I will need to extend the class and alter the method myself?

Thanks.

A: 

The purpose of Mocks and Stubs is to replace relying on functionality of dependencies, e.g. when you have something like

class Foo
{
    public function __construct($apiConnector) {
        $this->apiConnector = $apiConnector
    }
}

where $apiConnector is the dependency used to make the call to the API, then you stub or mock that dependency with your own implementation. Since that dependency is invoked through it's public facing interface by Foo, you stub the method that triggers the protected method within the dependency.

If, however, there is no dependency, but the call to the API is made from the testclass, then you have to write a custom class that extends your testclass and implements it's own API calling function, e.g.

class FooMock extends Foo
{
    protected function queryAPI()
    {
        return $fixture;
    }
}

You will then test this class instead of the actual class.

If your class is actually connecting to a WebService, see the chapter Stubbing and Mocking WebServices

Gordon
The method that calls the protected one does a lot of processing. It validates the arguments, calls the API, passes the response to a response object where it is in then parsed, and finally the response object is returned. I want to test that the method returns a valid Response object, so I'm not sure what I should be testing here.
Stephen Melrose
@Stephen just for clarity, the method you want to stub is within the class to be tested or is it a dependency, e.g. a separate class?
Gordon
@Gordon The method I want to stub is a protected method within the same class as the public method that calls it. The public method does other processing I want to test besides calling the protected method. What I want to do is remove the dependency on the API by making the protected method return a static fixture instead, so the rest of the process in the public method can run and be tested properly. If that makes sense.
Stephen Melrose
@Gordon That's pretty much what I thought, thank you. I may instead think about re-writing my class so I can inject an API connector instead. Just seems a tad overkill for essentially one API call, but it does make more design sense.
Stephen Melrose
It appears you can actually mock protected methods too, FYI.
Stephen Melrose
@Stephen you can also make protected methods accessible with PHPUnit, but if I understand your scenario correctly, you do not have any dependencies to stub but want to change the very behavior of the testclass itself.
Gordon