Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocking Aws\Common\InstanceMetadata\InstanceMetadataClient #44

Closed
poisa opened this issue Feb 12, 2013 · 4 comments
Closed

Mocking Aws\Common\InstanceMetadata\InstanceMetadataClient #44

poisa opened this issue Feb 12, 2013 · 4 comments

Comments

@poisa
Copy link
Contributor

poisa commented Feb 12, 2013

Is there a way to mock/stub this in order to develop locally? This calls a URL only available from within an EC2 instance so I'm trying to create a mock but I'm failing miserably.

I'm attempting to do this with PHPUnit but for some reason it is expecting that I send a parameter to send() which is strange since the real object is not expecting this.

Warning: Missing argument 1 for Mock_InstanceMetadataClient_1341b3cc::send(), called in ...IndexController.php line 38
// IndexController.php (lines 38-39)
...
$response = $client->get('user-data')->send();
var_dump($response->json());
...
// StubInstanceMetadata.php
namespace Stub\Amazon;

use PHPUnit_Framework_TestCase;

class StubInstanceMetadata extends PHPUnit_Framework_TestCase
{
    private $_stub;

    public function __construct()
    {

        // Create a stub for the SomeClass class.
        $stub = $this->getMockBuilder('Aws\Common\InstanceMetadata\InstanceMetadataClient')
                     ->disableOriginalConstructor()
                     ->setMethods(array('get', 'send'))
                     ->getMock();

        $stub->expects($this->any())
             ->method('get')
             ->will($this->returnSelf());

        $stub->expects($this->any())
             ->method('send')
             ->will($this->returnValue(new StubInstanceMetadataResponse())); // I have a similar object for the response with expects a ->json() call and returns an array

        $this->_stub = $stub;
    }

    public function getStub()
    {
        return $this->_stub;
    }
}```
@mtdowling
Copy link
Member

This should be much easier to do using the master branch. One of the changes that will go out in the next release is the addition of the getInstanceProfileCredentials() method to Aws\Common\InstanceMetadata\InstanceMetadataClient:

public function getInstanceProfileCredentials()

It would be much easier to mock this method to return a special credentials object. Does that help, or would you still want help mocking the current implementation?

@poisa
Copy link
Contributor Author

poisa commented Feb 13, 2013

Michael, thanks for your help. I don't mind mocking that method (or using
another branch) but I don't see how this will help me. Mind you that my
understanding of the sdk is quite basic and that my first encounter with
Guzzle was when I popped the hood on the sdk!

OK, so lets say I mock getInstanceProfileCredentials(), how do I get from
there to the user-data? Will this solution work offline? (just curious
about the offline thing, not that I need it, but I DO need to work with the
user-data!)

Much appreciated!

@mtdowling
Copy link
Member

I'm attempting to do this with PHPUnit but for some reason it is expecting that I send a parameter to send() which is strange since the real object is not expecting this.

The send method you're mocking requires a Guzzle\Http\Message\RequestInterface object. You'll need to ensure that a request is passed to the method in order to mock it correctly.

OK, so lets say I mock getInstanceProfileCredentials(), how do I get from
there to the user-data? Will this solution work offline? (just curious
about the offline thing, not that I need it, but I DO need to work with the
user-data!)

Mocking that method wont actually help you retrieve user data.

How you mock the various behavior of retrieving things from the instance metadata server is up to you. You can add an abstraction layer over the client and mock your abstraction layer. Alternatively, you could add a Guzzle\Plugin\Mock\MockPlugin to the client and queue up an array of HTTP responses with the plugin: http://guzzlephp.org/guide/plugins.html#mock-plugin. We actually use this technique in some of our tests of the client. Here are a mocked HTTP responses: https://github.com/aws/aws-sdk-php/tree/master/tests/mock/metadata. Our unit test for the metadata client gives a good example of how to use the mock plugin: https://github.com/aws/aws-sdk-php/blob/master/tests/Aws/Tests/Common/InstanceMetadata/InstanceMetadataClientTest.php.

@poisa
Copy link
Contributor Author

poisa commented Feb 13, 2013

You can add an abstraction layer over the client and mock your abstraction layer

I got so obsessed with making the mock work that I completely missed the easiest solution. I will still check the mock plugin out especially since I see myself doing this over pretty soon, but given the deadlines this is by far the fastest solution (and a pretty decent one too).

Michael, thank you so much for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants