Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Released version 0.6

  • Loading branch information...
commit 85ea4d0d23f2fe5aec64648291fb8f7d3a3cc1ed 2 parents a716d62 + 3f20163
Andrew Coulton authored
20 CHANGELOG.md
View
@@ -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  README.md
View
@@ -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)**
163 classes/mimic/unittest/testcase.php
View
@@ -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 classes/request/client/mimic.php
View
@@ -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();
@@ -145,4 +151,4 @@ protected function _send_external($request)
return $client->_send_message($request);
}
-} // End Request_Client_Mimic
+} // End Request_Client_Mimic
6 guide/mimic/config.md
View
@@ -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
-------------------------|------------
@@ -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 guide/mimic/customising.md
View
@@ -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
@@ -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 guide/mimic/index.md
View
@@ -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
@@ -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.
@@ -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
@@ -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  guide/mimic/matching.md
View
@@ -131,4 +131,4 @@ wildcards later.
);
---
-Continue to [Customising Responses](customising)
+Continue to [Customising Responses](customising.md)
14 guide/mimic/menu.md
View
@@ -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 guide/mimic/recording.md
View
@@ -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);
@@ -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)
133 guide/mimic/testing.md
View
@@ -10,30 +10,46 @@ The usual workflow would be:
* Build your unit tests to excercise your application code, and enable Mimic in
the setUp method of your tests.
-* Run the unit tests with [recording](recording) enabled to allow Mimic to record the real-world
+* Run the unit tests with [recording](recording.md) enabled to allow Mimic to record the real-world
behaviour of the external services you are accessing.
-* [Customise](customising) and tidy up your request and response definitions -
+* [Customise](customising.md) and tidy up your request and response definitions -
remembering to remove any sensitive details.
* Commit the tests and scenarios to source control, for later re-use on other
developer machines, CI servers, etc.
* If and when external APIs change (or you could schedule a regular check) re-run
-the tests with [updating](updating) enabled to automatically refresh your
+the tests with [updating](updating.md) enabled to automatically refresh your
definitions with new response formats and content, updating your unit tests and
application code accordingly.
## Basic usage with PHPUnit
-For basic usage with PHPUnit, you could simply build a test case like this:
+For most common testing, Mimic comes bundled with a [Mimic_Unittest_Testcase]
+base class which provides a useful set of assertions and activates Mimic with
+a clean stack in the setUp method. You can of course easily incorporate Mimic within
+any test method or class, for example if it's only required for a few of your tests.
- class APITest extends Unittest_Testcase
+You could therefore simply build a test case like this:
+
+ class APITest extends Mimic_Unittest_Testcase
{
- public static function setUpBeforeClass()
+
+ /**
+ * Mimic will set the scenario name to this during setUp (if not NULL)
+ * @var string
+ */
+ protected $_mimic_default_scenario = 'api_foo';
+
+ public static function setUp()
{
- // Activate Mimic and set recording mode from environment var
- // You can equally just use the config from your config files
- Mimic::instance()
- ->enable_recording(Arr::get($_SERVER, 'MIMIC_RECORD', FALSE));
- ->enable_updating(Arr::get($_SERVER, 'MIMIC_UPDATE', FALSE));
+ parent::setUp();
+
+ /*
+ * If you want to set recording and updating mode from environment variables (may be
+ * useful for ease) rather than config, you can do something like this. Otherwise, the
+ * base setUp() will do everything you need.
+ */
+ $this->mimic->enable_recording(Arr::get($_SERVER,'MIMIC_ENABLE_RECORD', FALSE) ? TRUE : FALSE);
+ $this->mimic->enable_updating(Arr::get($_SERVER,'MIMIC_ENABLE_UPDATE', FALSE) ? TRUE : FALSE);
}
/**
@@ -65,32 +81,26 @@ high-level behaviour. You'll probably want to test the observable external actio
of your code - for example verifying that your code is not calling more API methods
than you expect, or that reading a resource is not making changes to it.
-Mimic provides a number of methods that allow you to access and inspect the requests
-your application code has made.
+The [Mimic_Unittest_Testcase] base class provides a set of useful assertion methods to
+verify common expectations.
-Method | Returns / Action
------------------------------|--------
-[Mimic::last_request] | [Request] object for the most recently executed request
-[Mimic::request_count] | The number of requests that have been executed
-[Mimic::request_history]\(id)| An array of requests (or a single element) in order executed
-[Mimic::reset_requests] | Reset the request stack for a fresh test
+Method | Tests
+------------------------------|--------
+assertMimicRequestCount | An expected number of requests were made
+assertMimicLastRequestURL | The last request URL
+assertMimicLastRequestMethod | The last request method
+assertMimicLastRequestHeader | A header value in the last request
+assertMimicLastRequestQuery | A query value in the last request
+assertMimicLastRequestBody | The body-content of the last request
+assertMimicRequestsContains | At least one request was made to a given URL (optionally, with a given method)
+assertMimicRequestsNotContains| No requests were made to the given URL (optionally, with a given method)
-[!!] Mimic operates as a singleton by default (as we can't inject an instance into
-the [Mimic_Request_Client]) so you need to call [Mimic::reset_requests] before
-each test - the easiest way to do this is in your setUp() method.
-
-So, your unit test code might look like this:
+### Testing individual requests
+To build on the test above, you could add the following to your testcase:
- class APITest extends Unittest_Testcase
+ class APITest extends Mimic_Unittest_Testcase
{
- protected $_mimic = NULL;
-
- public function setUp()
- {
- $this->_mimic = Mimic::instance();
- $this->_mimic->reset_requests();
- }
-
+
public function test_api_gets_version()
{
$api = new MyApi;
@@ -100,14 +110,57 @@ So, your unit test code might look like this:
*/
$version = $api->get_version();
$this->assertEquals('1.2', $version);
-
- // Verify expected web request calls
- $this->assertEquals(1, $this->_mimic->request_count());
- $last_request = $this->_mimic->last_request();
- $this->assertEquals('http://my.api.com/version', $last_request->uri());
- $this->assertEquals('GET', $last_request()->method());
+
+ // Check the web request happened
+ $this->assertMimicRequestCount(1);
+ $this->assertMimicLastRequestURL('http://my.api.com/version');
+ $this->assertMimicLastRequestMethod('GET');
}
}
+### Requests (not)? contains
+Obviously, assertMimicRequestsContains and assertMimicRequestsNotContains are less powerful than the tests against
+last request, but are also less brittle over time and allow many simple checks. For example, perhaps you want to
+establish that an API call only makes a connection if the client has supplied authentication. You'll obviously
+want to verify that the method throws an exception (or whatever your logic flow requires). But you may also want
+to be sure that the exception was thrown before the request was sent - in that case you could test:
+
+ public function test_api_only_deletes_if_authenticated()
+ {
+ $api = new MyApi;
+
+ try
+ {
+ $api->delete(5);
+ }
+ catch(MyApi_Exception_Not_Authenticated $e)
+ {
+ $this->assertMimicRequestsNotContains('http://api.foo.thing/5', 'DELETE');
+ return;
+ }
+
+ $this->fail('Expected MyApi_Exception_Not_Authenticated was not thrown');
+ }
+
+### More complex tests
+
+For other expectations, Mimic provides a number of methods that allow you to access and
+inspect the requests your application code has made.
+
+Method | Returns / Action
+-----------------------------|--------
+[Mimic::last_request] | [Request] object for the most recently executed request
+[Mimic::request_count] | The number of requests that have been executed
+[Mimic::request_history]\(id)| An array of requests (or a single element) in order executed
+[Mimic::reset_requests] | Reset the request stack for a fresh test
+
+[!!] Mimic operates as a singleton by default (as we can't inject an instance into
+the [Mimic_Request_Client]) so you need to call [Mimic::reset_requests] before
+each test - the easiest way to do this is in your setUp() method. The [Mimic_Unittest_Testcase]
+base class handles this for you.
+
+If you find you're regularly using the same custom assertions, please do [send a pull request](https://github.com/acoulton/mimic/pulls)
+for inclusion in the base test cases.
+
---
-Continue to [Updating Definitions](updating)
+Continue to [Updating Definitions](updating.md)
4 guide/mimic/updating.md
View
@@ -23,7 +23,7 @@ recording the details of exactly what was executed to generate the returned resp
## Enabling updating
To enable updating mode, simply call [Mimic::enable_updating]\(TRUE) or set the
-appropriate value in your [configuration](config).
+appropriate value in your [configuration](config.md).
---
-Continue to [Configuration](config)
+Continue to [Configuration](config.md)
39 tests/mimic/ClientTest.php
View
@@ -243,6 +243,43 @@ public function test_should_record_and_return_external_request_if_updating_enabl
$returned_response = $this->_client->_send_message($request);
$this->assertSame($response, $returned_response, "The same response instance was returned");
}
+
+ public function provider_should_assign_request_content_length_if_missing()
+ {
+ return array(
+ array(NULL, '5', '5'),
+ array('foo', NULL, '3'),
+ array(NULL, NULL, '0'),
+ array('foo', '0', '0')
+ );
+ }
+
+ /**
+ * @group ticket.5
+ * @dataProvider provider_should_assign_request_content_length_if_missing
+ */
+ public function test_should_assign_request_content_length_if_missing($body, $set_length, $expect_length)
+ {
+ // Create a request
+ $request = Request::factory('http://foo.bar.com/a/page');
+ $request->body($body);
+ if ($set_length !== NULL)
+ {
+ $request->headers('content-length', $set_length);
+ }
+ $response = $request->create_response();
+
+ // Set up Mimic expectations
+ $this->_mock_mimic_methods($this->once(), 'enable_updating', NULL, FALSE);
+
+ // Mock a store to return response
+ $this->_mock_store_methods($this->once(), 'load', $request, $response);
+
+ // Execute and check the content-length header is present
+ $this->_client->_send_message($request);
+ $this->assertSame($expect_length, $request->headers('content-length'));
+
+ }
}
@@ -258,4 +295,4 @@ public function _send_message(Request $request)
return $request->response();
}
-}
+}
382 tests/mimic/TestCaseTest.php
View
@@ -0,0 +1,382 @@
+<?php defined('SYSPATH') or die('Kohana bootstrap needs to be included before tests run');
+
+/**
+ * Tests for the Mimic_Unittest_Testcase base testing class
+ *
+ * @group mimic
+ * @group mimic.testcase
+ *
+ * @package Mimic
+ * @category Tests
+ * @author Andrew Coulton
+ * @copyright (c) 2011 Ingenerator
+ * @license http://kohanaframework.org/license
+ */
+class Mimic_TestCaseTest extends Unittest_Testcase {
+
+ public function test_setup_should_assign_mimic_instance_to_class()
+ {
+ $testcase = new Mimic_TestCase_Foo;
+ $mimic = Mimic::instance(array(), TRUE);
+ $testcase->setUp();
+
+ $this->assertSame($mimic, $testcase->mimic);
+ return $testcase;
+ }
+
+ /**
+ * @depends test_setup_should_assign_mimic_instance_to_class
+ */
+ public function test_setup_should_reset_requests(Mimic_TestCase_Foo $testcase)
+ {
+ // Pretend a request happened
+ $request = Request::factory('http://foo.bar.com/ok');
+ $testcase->mimic->log_request($request);
+ $this->assertEquals(1, $testcase->mimic->request_count(), "Verify expectation pre-test");
+
+ // Setup
+ $testcase->setUp();
+
+ $this->assertEquals(0, $testcase->mimic->request_count());
+ }
+
+ public function provider_setup_should_set_scenario_if_set_in_class()
+ {
+ return array(
+ array(NULL, 'default'),
+ array('foo', 'foo')
+ );
+ }
+
+ /**
+ * @dataProvider provider_setup_should_set_scenario_if_set_in_class
+ */
+ public function test_setup_should_set_scenario_if_set_in_class($property, $expected)
+ {
+ $testcase = new Mimic_TestCase_Foo;
+ $testcase->_mimic_default_scenario = $property;
+ $mimic = Mimic::instance(array(), TRUE);
+ $mimic->load_scenario('default');
+
+ $testcase->setUp();
+
+ $this->assertEquals($expected, $mimic->get_active_scenario());
+ }
+
+ /**
+ * Helper method to test that an assertion produces expected pass/fail result
+ *
+ * @param Mimic_Testcase $testcase The testcase instance
+ * @param string $method The method to call
+ * @param array $args Arguments to pass to the method
+ * @param boolean $should_pass Whether or not the assertion should pass
+ * @return void
+ */
+ protected function _test_assertion($testcase, $method, $args, $should_pass)
+ {
+ try
+ {
+ // Call the assertion method
+ call_user_func_array(array($testcase, $method), $args);
+ }
+ catch (PHPUnit_Framework_ExpectationFailedException $e)
+ {
+ // Check that this is expected to fail
+ if ($should_pass)
+ {
+ $this->fail('Unexpected assertion failure with message '.$e->getMessage());
+ }
+ return;
+ }
+ catch (PHPUnit_Framework_AssertionFailedError $e)
+ {
+ // Check that this is expected to fail
+ if ($should_pass)
+ {
+ $this->fail('Unexpected assertion failure with message '.$e->getMessage());
+ }
+ return;
+ }
+
+ // Check that it is expected to pass
+ if ( ! $should_pass)
+ {
+ $this->fail("Unexpected assertion pass for method $method");
+ }
+ }
+
+ /**
+ * Gets a testcase with a mock mimic attached ready for use in testing
+ * @param string $method
+ * @param mixed $return
+ * @return Mimic_TestCase_Foo
+ */
+ protected function _testcase_with_mock_mimic($method, $return)
+ {
+ $testcase = new Mimic_TestCase_Foo;
+
+ // Mock a Mimic to return the matching value
+ $testcase->mimic = $this->getMock('Mimic');
+ $testcase->mimic->expects($this->once())
+ ->method($method)
+ ->will($this->returnValue($return));
+
+ return $testcase;
+ }
+
+ /**
+ * Gets a mock request with one method mocked to return a value for testing
+ * @param string $method
+ * @param mixed $return
+ * @return Request
+ */
+ protected function _mock_request($method = NULL, $return = NULL)
+ {
+ // Mock a request
+ $request = $this->getMock('Request', array(),array(), '', FALSE);
+
+ // Mock a method if required
+ if ($method !== NULL)
+ {
+ $request->expects($this->once())
+ ->method($method)
+ ->will($this->returnValue($return));
+ }
+
+ return $request;
+ }
+
+ public function provider_should_assert_mimic_request_count()
+ {
+ return array(
+ array(1, 1, TRUE),
+ array(1, 0, FALSE)
+ );
+ }
+
+ /**
+ * @dataProvider provider_should_assert_mimic_request_count
+ * @param integer $mock_count
+ * @param integer $expected
+ * @param boolean $should_pass
+ */
+ public function test_should_assert_mimic_request_count($mock_count, $expected, $should_pass)
+ {
+ $testcase = $this->_testcase_with_mock_mimic('request_count', $mock_count);
+
+ $this->_test_assertion($testcase, 'assertMimicRequestCount', array($expected), $should_pass);
+ }
+
+ public function provider_should_assert_last_request_url()
+ {
+ return array(
+ array('http://www.foo.bar/abc', 'http://www.foo.bar/abc', TRUE),
+ array('http://www.foo.bar/abc', 'http://www.foo.bar/foo', FALSE)
+ );
+ }
+
+ /**
+ * @dataProvider provider_should_assert_last_request_url
+ * @param string $mock_url
+ * @param integer $expected
+ * @param boolean $should_pass
+ */
+ public function test_should_assert_last_request_url($mock_url, $expected, $should_pass)
+ {
+ $testcase = $this->_testcase_with_mock_mimic('last_request',
+ $this->_mock_request('uri', $mock_url));
+
+ $this->_test_assertion($testcase, 'assertMimicLastRequestURL', array($expected), $should_pass);
+ }
+
+ public function provider_should_assert_last_request_method()
+ {
+ return array(
+ array('GET', 'GET', TRUE),
+ array('GET', 'POST', FALSE)
+ );
+ }
+
+ /**
+ * @dataProvider provider_should_assert_last_request_method
+ * @param string $mock_method
+ * @param integer $expected
+ * @param boolean $should_pass
+ */
+ public function test_should_assert_last_request_method($mock_method, $expected, $should_pass)
+ {
+ $testcase = $this->_testcase_with_mock_mimic('last_request',
+ $this->_mock_request('method', $mock_method));
+
+ $this->_test_assertion($testcase, 'assertMimicLastRequestMethod', array($expected), $should_pass);
+ }
+
+ public function provider_should_assert_last_request_header()
+ {
+ return array(
+ array('X-foo', 'bar', 'bar', TRUE),
+ array('X-foo', 'bar', 'biddy', FALSE)
+ );
+ }
+
+ /**
+ * @dataProvider provider_should_assert_last_request_header
+ * @param string $header
+ * @param string $mock_value
+ * @param integer $expected
+ * @param boolean $should_pass
+ */
+ public function test_should_assert_last_request_header($header, $mock_value, $expected, $should_pass)
+ {
+ $request = $this->_mock_request();
+ $request->expects($this->once())
+ ->method('headers')
+ ->with($header)
+ ->will($this->returnValue($mock_value));
+
+ $testcase = $this->_testcase_with_mock_mimic('last_request',
+ $request);
+
+ $this->_test_assertion($testcase, 'assertMimicLastRequestHeader', array($header, $expected), $should_pass);
+ }
+
+ public function provider_should_assert_last_request_query()
+ {
+ return array(
+ array('foo', 'bar', 'bar', TRUE),
+ array('foo', 'bar', 'biddy', FALSE)
+ );
+ }
+
+ /**
+ * @dataProvider provider_should_assert_last_request_query
+ * @param string $key
+ * @param string $mock_value
+ * @param integer $expected
+ * @param boolean $should_pass
+ */
+ public function test_should_assert_last_request_query($key, $mock_value, $expected, $should_pass)
+ {
+ $request = $this->_mock_request();
+ $request->expects($this->once())
+ ->method('query')
+ ->with($key)
+ ->will($this->returnValue($mock_value));
+
+ $testcase = $this->_testcase_with_mock_mimic('last_request',
+ $request);
+
+ $this->_test_assertion($testcase, 'assertMimicLastRequestQuery', array($key, $expected), $should_pass);
+ }
+
+ public function provider_should_assert_last_request_body()
+ {
+ return array(
+ array('body-foo', 'body-foo', TRUE),
+ array('body-foo', 'body-bar', FALSE)
+ );
+ }
+
+ /**
+ * @dataProvider provider_should_assert_last_request_body
+ * @param string $mock_body
+ * @param integer $expected
+ * @param boolean $should_pass
+ */
+ public function test_should_assert_last_request_body($mock_body, $expected, $should_pass)
+ {
+ $testcase = $this->_testcase_with_mock_mimic('last_request',
+ $this->_mock_request('body', $mock_body));
+
+ $this->_test_assertion($testcase, 'assertMimicLastRequestBody', array($expected), $should_pass);
+ }
+
+ public function provider_should_assert_or_not_requests_contains()
+ {
+ $requests = array(
+ array('method'=>'GET', 'uri' => 'http://foo.bar.com/foo'),
+ array('method'=>'POST', 'uri' => 'http://foo.bar.com/foo'),
+ array('method'=>'GET', 'uri' => 'http://foo.bar.com/bar'),
+ );
+ return array(
+ array($requests, 'http://foo.bar.com/foo', 'POST', TRUE),
+ array($requests, 'http://foo.bar.com/foo', NULL, TRUE),
+ array($requests, 'http://foo.bar.com/foo', 'PUT', FALSE),
+ array($requests, 'http://foo.bar.com/bar', 'GET', TRUE),
+ );
+ }
+
+ /**
+ * Helper method, as the test strap for assertMimicRequestsContains and
+ * assertMimicRequestsNotContains is very similar.
+ *
+ * @param string $method
+ * @param array $mock_requests
+ * @param string $test_url
+ * @param string $test_method
+ * @param string $should_pass
+ */
+ protected function _test_should_or_not_contain($method, $mock_requests, $test_url, $test_method, $should_pass)
+ {
+ // Build an array of mock requests for the stack
+ $request_history = array();
+ foreach ($mock_requests as $mock_request)
+ {
+ $request = $this->_mock_request();
+
+ // Request::uri() will only be called if the method matches the search
+ $request->expects($this->any())
+ ->method('uri')
+ ->will($this->returnValue($mock_request['uri']));
+
+ // Request::method() will only be called if matching on it
+ $request->expects($this->any())
+ ->method('method')
+ ->will($this->returnValue($mock_request['method']));
+ $request_history[] = $request;
+ }
+
+ // Mock the testcase
+ $testcase = $this->_testcase_with_mock_mimic('request_history', $request_history);
+
+ // Call and test the assertion
+ $this->_test_assertion($testcase, $method, array($test_url, $test_method), $should_pass);
+ }
+
+ /**
+ * @dataProvider provider_should_assert_or_not_requests_contains
+ * @param array $mock_requests
+ * @param string $test_url
+ * @param string $test_method
+ * @param boolean $should_contain Whether the stack should contain the request
+ */
+ public function test_should_assert_requests_contains($mock_requests, $test_url, $test_method, $should_contain)
+ {
+ $this->_test_should_or_not_contain('assertMimicRequestsContains',
+ $mock_requests, $test_url, $test_method, $should_contain);
+ }
+
+ /**
+ * @dataProvider provider_should_assert_or_not_requests_contains
+ * @param array $mock_requests
+ * @param string $test_url
+ * @param string $test_method
+ * @param boolean $should_contain Whether the stack should contain the request
+ */
+ public function test_should_assert_requests_not_contains($mock_requests, $test_url, $test_method, $should_contain)
+ {
+ $should_pass = ! $should_contain;
+ $this->_test_should_or_not_contain('assertMimicRequestsNotContains',
+ $mock_requests, $test_url, $test_method, $should_pass);
+ }
+
+
+}
+
+/**
+ * Extension as the base class is abstract
+ */
+class Mimic_TestCase_Foo extends Mimic_Unittest_Testcase
+{
+ public $_mimic_default_scenario = NULL;
+}
18 tests/mimic/request/store/PlaybackTest.php
View
@@ -1,12 +1,6 @@
<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
/**
- * These tests require the vfsStream mock filesystem driver
- * from https://github.com/mikey179/vfsStream/
- */
-require_once 'vfsStream/vfsStream.php';
-
-/**
* Unit tests for the playback functionality of the Mimic_Request_Store class
*
* @group mimic
@@ -34,6 +28,18 @@ class Mimic_Request_Store_PlaybackTest extends Unittest_TestCase {
protected $_file_system = null;
/**
+ * Requires the vfsStream extension for tests
+ */
+ public static function setUpBeforeClass()
+ {
+ /**
+ * These tests require the vfsStream mock filesystem driver
+ * from https://github.com/mikey179/vfsStream/
+ */
+ require_once 'vfsStream/vfsStream.php';
+ }
+
+ /**
* Sets up a mock file system using vfsStream and a mock mimic that will use
* this as the base path for request storage
*/
12 tests/mimic/request/store/RecordingTest.php
View
@@ -1,12 +1,6 @@
<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
/**
- * These tests require the vfsStream mock filesystem driver
- * from https://github.com/mikey179/vfsStream/
- */
-require_once 'vfsStream/vfsStream.php';
-
-/**
* Unit tests for the recording functionality of the Mimic_Request_Store class
*
* @group mimic
@@ -40,6 +34,12 @@ class Mimic_Request_Store_RecordingTest extends Unittest_TestCase {
*/
public static function setUpBeforeClass()
{
+ /**
+ * These tests require the vfsStream mock filesystem driver
+ * from https://github.com/mikey179/vfsStream/
+ */
+ require_once 'vfsStream/vfsStream.php';
+
parent::setUpBeforeClass();
// Override Kohana::$config->load() to return our test configs
19 tests/mimic/response/FormatterBaseTest.php
View
@@ -1,12 +1,6 @@
<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
/**
- * These tests require the vfsStream mock filesystem driver
- * from https://github.com/mikey179/vfsStream/
- */
-require_once 'vfsStream/vfsStream.php';
-
-/**
* Base unit tests for all Mimic_Response_Formatter classes
*
* @package Mimic
@@ -21,6 +15,19 @@
protected $_expect_extension = NULL;
protected $_file_system = NULL;
+ /**
+ * Requires the vfsStream extension for tests
+ */
+ public static function setUpBeforeClass()
+ {
+ /**
+ * These tests require the vfsStream mock filesystem driver
+ * from https://github.com/mikey179/vfsStream/
+ */
+ require_once 'vfsStream/vfsStream.php';
+ }
+
+
public function setUp()
{
parent::setUp();
Please sign in to comment.
Something went wrong with that request. Please try again.