Skip to content

Commit

Permalink
Released version 0.6
Browse files Browse the repository at this point in the history
  • Loading branch information
acoulton committed Mar 15, 2012
2 parents a716d62 + 3f20163 commit 85ea4d0
Show file tree
Hide file tree
Showing 17 changed files with 760 additions and 86 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,20 @@
# Mimic for PHP
#(c) 2012 Andrew Coulton
# Changelog

## v0.6

### New features
* Use .md extension for userguide links so that they can be read on github
(requires latest version of Kohana 3.2 to browse in the userguide module)
* Provides a base unittest testcase class for common assertions and requirements (see issue #4)
*

### Bugfixes
* Explicitly sets Request content-length header if not present - fixes #5
* Only requires vfsStream to run Mimic's own unit tests - previously caused an
error if trying to run other testcases in the project without vfsStream installed.

## v0.5

* First version
2 changes: 1 addition & 1 deletion README.md
@@ -1,6 +1,6 @@
# Mimic

**[View builds]((http://travis-ci.org/acoulton/mimic) | master: ![Build status - master branch](https://secure.travis-ci.org/acoulton/mimic.png?branch=master) |
**[View builds](http://travis-ci.org/acoulton/mimic) | master: ![Build status - master branch](https://secure.travis-ci.org/acoulton/mimic.png?branch=master) |
develop: ![Build Status - develop branch](https://secure.travis-ci.org/acoulton/mimic.png?branch=develop) |
overall: ![Build Status - overall](https://secure.travis-ci.org/acoulton/mimic.png)**

Expand Down
163 changes: 163 additions & 0 deletions classes/mimic/unittest/testcase.php
@@ -0,0 +1,163 @@
<?php
defined('SYSPATH') or die('No direct script access.');

/**
* Base class for test cases that use Mimic to test interaction with external web
* services, handling set up and tear down of the Mimic request client and providing
* suitable assertions as required.
*
* @package Mimic
* @category TestInterface
* @author Andrew Coulton
* @copyright (c) 2011 Ingenerator
* @license http://kohanaframework.org/license
*/
abstract class Mimic_Unittest_Testcase extends Unittest_TestCase
{
/**
* The current Mimic instance
* @var Mimic
*/
public $mimic = NULL;

/**
* If set, will load a default scenario in setUp
* @var string
*/
protected $_mimic_default_scenario = NULL;

/**
* Stores a reference to the Mimic instance, and resets requests for the
* next test execution
*/
public function setUp() {
parent::setUp();
$this->mimic = Mimic::instance();
$this->mimic->reset_requests();
if ($this->_mimic_default_scenario)
{
$this->mimic->load_scenario($this->_mimic_default_scenario);
}
}

/**
* Asserts that an expected number of requests were made
* @param integer $expected
*/
public function assertMimicRequestCount($expected)
{
$this->assertEquals($expected, $this->mimic->request_count());
}

/**
* Asserts that the URL of the most recent request is equal to an expected value
* @param string $expected
*/
public function assertMimicLastRequestURL($expected)
{
$this->assertEquals($expected, $this->mimic->last_request()->uri());
}

/**
* Asserts that the HTTP request method of the most recent request is equal to
* an expected value
*
* @param string $expected
*/
public function assertMimicLastRequestMethod($expected)
{
$this->assertEquals($expected, $this->mimic->last_request()->method());
}

/**
* Asserts that the most recent request included a header with the given value
*
* @param string $header The header name
* @param string $expected The expected value
*/
public function assertMimicLastRequestHeader($header, $expected)
{
$this->assertEquals($expected, $this->mimic->last_request()->headers($header));
}

/**
* Asserts that the most recent request included an expected $_GET parameter
*
* @param string $key
* @param string $expected
*/
public function assertMimicLastRequestQuery($key, $expected)
{
$this->assertEquals($expected, $this->mimic->last_request()->query($key));
}

/**
* Asserts that the request body of the most recent request was as expected
* @param string $expected
*/
public function assertMimicLastRequestBody($expected)
{
$this->assertEquals($expected, $this->mimic->last_request()->body());
}

/**
* Searches the request history for a request to the given URL and (optionally)
* with the specified method, returning TRUE or FALSE.
*
* @param string $url
* @param string $method
* @return boolean
*/
protected function _search_request_history($url, $method)
{
foreach ($this->mimic->request_history() as $request)
{
if (($method !== NULL) AND ($method !== $request->method()))
{
continue;
}

if ($request->uri() === $url)
{
return TRUE;
}
}

// Nothing found
return FALSE;

}

/**
* Verify that a request (optionally with a specified method) was made to the
* given URL at some point in execution - for requests where the sequence doesn't
* matter, this is obviously less brittle than asserting a specific request.
*
* @param string $url
* @param string $method
*/
public function assertMimicRequestsContains($url, $method = NULL)
{
if ( ! $this->_search_request_history($url, $method))
{
$this->fail("Expected $method request to $url and none was made");
}
}

/**
* Verify that a request (optionally with a specified method) was not made to
* the given URL at any point in execution - for requests where the sequence doesn't
* matter, this is obviously less brittle than asserting a specific request.
*
* @param string $url
* @param string $method
*/
public function assertMimicRequestsNotContains($url, $method = NULL)
{
if ($this->_search_request_history($url, $method))
{
$this->fail("A $method request was made to $url");
}
}

}
8 changes: 7 additions & 1 deletion classes/request/client/mimic.php
Expand Up @@ -33,6 +33,12 @@ class Request_Client_Mimic extends Request_Client_External
*/
public function _send_message(Request $request)
{
// Set a content-length if not set already (fixes #5)
if ($request->headers('content-length') === NULL)
{
$request->headers('content-length', (string) strlen($request->body()));
}

// Create OR retrieve the Mimic and Mimic_Request_Store instances
$mimic = $this->mimic();
$store = $this->store();
Expand Down Expand Up @@ -145,4 +151,4 @@ protected function _send_external($request)
return $client->_send_message($request);
}

} // End Request_Client_Mimic
} // End Request_Client_Mimic
6 changes: 3 additions & 3 deletions guide/mimic/config.md
Expand Up @@ -12,11 +12,11 @@ debug_headers | FALSE | Add X-Mimic debug headers to
enable_recording| FALSE | Allow recording of requests that aren't matched?
enable_updating | FALSE | Update matched requests by executing and storing new response?
external_client | NULL | Specify an external client to use when executing requests - if NULL will use whatever is set for [Request_Client_External]::$client
response_formatters | array | An array of [formatters](formatters) to use for given content-types
response_formatters | array | An array of [formatters](formatters.md) to use for given content-types

## Default formatters

As shipped, Mimic uses the following default [formatters](formatters):
As shipped, Mimic uses the following default [formatters](formatters.md):

Content-Type | Formatter
-------------------------|------------
Expand All @@ -31,4 +31,4 @@ application/rss+xml |[Mimic_Response_Formatter_XML]
* (others) |[Mimic_Response_Formatter]

---
Continue to [Response Formatters](formatters)
Continue to [Response Formatters](formatters.md)
6 changes: 3 additions & 3 deletions guide/mimic/customising.md
Expand Up @@ -70,7 +70,7 @@ straightforward:
)
)));

For more on how requests are matched, see [the section on request matching](matching).
For more on how requests are matched, see [the section on request matching](matching.md).

## Response bodies

Expand All @@ -82,10 +82,10 @@ purposes if required. Likewise the same response body can be used by multiple
request definitions (for example, if different response headers are required but
the body is the same).

Response bodies are stored using [response formatters](formatters) which apply an
Response bodies are stored using [response formatters](formatters.md) which apply an
appropriate file extension for the content type and can convert the content to a
human readable format (for example, adding newlines and indentation to JSON responses)
for easier editing and verification.

---
Continue to [Testing with Mimic](testing)
Continue to [Testing with Mimic](testing.md)
14 changes: 7 additions & 7 deletions guide/mimic/index.md
Expand Up @@ -5,12 +5,12 @@ web services.

If you've used the [VCR module for Ruby](https://github.com/myronmarston/vcr),
you'll recognise the concept. By default, [Mimic] intercepts all external requests
and throws an exception. When [recording mode](recording) is enabled, [Mimic] executes the
and throws an exception. When [recording mode](recording.md) is enabled, [Mimic] executes the
external request and records the response (complete with headers and response
status) to disk. Future requests to the external resource will return the
response that has been stored on disk, allowing increased performance
and more importantly an idempotent [implementation of unit and functional
tests](testing) with a minimum of configuration or mocking code.
tests](testing.md) with a minimum of configuration or mocking code.

## Scenarios
Mimic supports multiple named scenarios (nothing more complex than a separate
Expand All @@ -30,13 +30,13 @@ By default, Mimic matches all of:
* URI Parameters
* Request Headers

However, [matching rules can be easily edited](matching) to allow looser
However, [matching rules can be easily edited](matching.md) to allow looser
matching of requests which can be useful if you want to return the same response
for multiple requests - for example to minimise the effort involved in supporting
query parameters that aren't relevant to your test scenario.

## Customising responses
Requests and responses are stored in [easily editable formats](customising),
Requests and responses are stored in [easily editable formats](customising.md),
allowing you to customise both the request and response for a variety of scenarios.
For example, you might want to edit the response to simulate an error condition that is difficult
to trigger from the client side.
Expand All @@ -47,14 +47,14 @@ authentication tokens or private content before committing to a source code
repository!**

Mimic aids review, source control and editing of responses by passing supported
content types (currently XML and JSON) through a [formatter](formatters) before
content types (currently XML and JSON) through a [formatter](formatters.md) before
saving. Formatters "pretty-print" the responses, introducing newlines, indentation,
and whitespace to make responses human-readable.

## Verifying application behaviour
In addition to replaying "canned" responses, Mimic keeps a history of requests
executed and responses returned. You can
[access the history from your test cases](testing#verifying-expectations)
[access the history from your test cases](testing.md#verifying-expectations)
to verify:

* That an expected pattern of requests were sent (for example, that a given
Expand All @@ -68,4 +68,4 @@ to verify:
* PHP 5.3 or greater

If you want to run the unit tests, you will need PHPUnit and the
[vfsStream](https://github.com/mikey179/vfsStream) virtual filesystem library.
[vfsStream](https://github.com/mikey179/vfsStream) virtual filesystem library.
2 changes: 1 addition & 1 deletion guide/mimic/matching.md
Expand Up @@ -131,4 +131,4 @@ wildcards later.
);

---
Continue to [Customising Responses](customising)
Continue to [Customising Responses](customising.md)
14 changes: 7 additions & 7 deletions guide/mimic/menu.md
@@ -1,8 +1,8 @@
## [Mimic]()
- [Recording](recording)
- [Matching Requests](matching)
- [Customising Responses](customising)
- [Testing with Mimic](testing)
- [Updating definitions](updating)
- [Configuration](config)
- [Response Formatters](formatters)
- [Recording](recording.md)
- [Matching Requests](matching.md)
- [Customising Responses](customising.md)
- [Testing with Mimic](testing.md)
- [Updating definitions](updating.md)
- [Configuration](config.md)
- [Response Formatters](formatters.md)
4 changes: 2 additions & 2 deletions guide/mimic/recording.md
Expand Up @@ -24,7 +24,7 @@ of the request and the response) and save it to disk for customisation and futur
use.

To use this feature, you'll need to enable recording mode either in your
[configuration](config) or by setting [Mimic::enable_recording]\(TRUE).
[configuration](config.md) or by setting [Mimic::enable_recording]\(TRUE).

// Enable recording
Mimic::instance()->enable_recording(TRUE);
Expand All @@ -34,4 +34,4 @@ To use this feature, you'll need to enable recording mode either in your
->execute();

---
Continue to [Matching Requests](matching)
Continue to [Matching Requests](matching.md)

0 comments on commit 85ea4d0

Please sign in to comment.