delete, select & insert upgraded More utility function (node to array, arrayToNode) XMLDB special move command PHP Unit Test
		
			
				
	
	
		
			758 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			758 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<html>
 | 
						|
<head>
 | 
						|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 | 
						|
<title>SimpleTest for PHP mock objects documentation</title>
 | 
						|
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
<div class="menu_back"><div class="menu">
 | 
						|
<a href="index.html">SimpleTest</a>
 | 
						|
                |
 | 
						|
                <a href="overview.html">Overview</a>
 | 
						|
                |
 | 
						|
                <a href="unit_test_documentation.html">Unit tester</a>
 | 
						|
                |
 | 
						|
                <a href="group_test_documentation.html">Group tests</a>
 | 
						|
                |
 | 
						|
                <span class="chosen">Mock objects</span>
 | 
						|
                |
 | 
						|
                <a href="partial_mocks_documentation.html">Partial mocks</a>
 | 
						|
                |
 | 
						|
                <a href="reporter_documentation.html">Reporting</a>
 | 
						|
                |
 | 
						|
                <a href="expectation_documentation.html">Expectations</a>
 | 
						|
                |
 | 
						|
                <a href="web_tester_documentation.html">Web tester</a>
 | 
						|
                |
 | 
						|
                <a href="form_testing_documentation.html">Testing forms</a>
 | 
						|
                |
 | 
						|
                <a href="authentication_documentation.html">Authentication</a>
 | 
						|
                |
 | 
						|
                <a href="browser_documentation.html">Scriptable browser</a>
 | 
						|
</div></div>
 | 
						|
<h1>Mock objects documentation</h1>
 | 
						|
        This page...
 | 
						|
        <ul>
 | 
						|
<li>
 | 
						|
            <a href="#what">What are mock objects?</a>
 | 
						|
        </li>
 | 
						|
<li>
 | 
						|
            <a href="#creation">Creating mock objects</a>.
 | 
						|
        </li>
 | 
						|
<li>
 | 
						|
            <a href="#stub">Mocks as actors</a> or stubs.
 | 
						|
        </li>
 | 
						|
<li>
 | 
						|
            <a href="#expectations">Mocks as critics</a> with expectations.
 | 
						|
        </li>
 | 
						|
<li>
 | 
						|
            <a href="#approaches">Other approaches</a> including mock libraries.
 | 
						|
        </li>
 | 
						|
</ul>
 | 
						|
<div class="content">
 | 
						|
        <p><a class="target" name="what"><h2>What are mock objects?</h2></a></p>
 | 
						|
            <p>
 | 
						|
                Mock objects have two roles during a test case: actor and critic.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                The actor behaviour is to simulate objects that are difficult to
 | 
						|
                set up or time consuming to set up for a test.
 | 
						|
                The classic example is a database connection.
 | 
						|
                Setting up a test database at the start of each test would slow
 | 
						|
                testing to a crawl and would require the installation of the
 | 
						|
                database engine and test data on the test machine.
 | 
						|
                If we can simulate the connection and return data of our
 | 
						|
                choosing we not only win on the pragmatics of testing, but can
 | 
						|
                also feed our code spurious data to see how it responds.
 | 
						|
                We can simulate databases being down or other extremes
 | 
						|
                without having to create a broken database for real.
 | 
						|
                In other words, we get greater control of the test environment.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                If mock objects only behaved as actors they would simply be
 | 
						|
                known as server stubs.
 | 
						|
                This was originally a pattern named by Robert Binder (Testing
 | 
						|
                object-oriented systems: models, patterns, and tools,
 | 
						|
                Addison-Wesley) in 1999.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                A server stub is a simulation of an object or component.
 | 
						|
                It should exactly replace a component in a system for test
 | 
						|
                or prototyping purposes, but remain lightweight.
 | 
						|
                This allows tests to run more quickly, or if the simulated
 | 
						|
                class has not been written, to run at all.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                However, the mock objects not only play a part (by supplying chosen
 | 
						|
                return values on demand) they are also sensitive to the
 | 
						|
                messages sent to them (via expectations).
 | 
						|
                By setting expected parameters for a method call they act
 | 
						|
                as a guard that the calls upon them are made correctly.
 | 
						|
                If expectations are not met they save us the effort of
 | 
						|
                writing a failed test assertion by performing that duty on our
 | 
						|
                behalf.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                In the case of an imaginary database connection they can
 | 
						|
                test that the query, say SQL, was correctly formed by
 | 
						|
                the object that is using the connection.
 | 
						|
                Set them up with fairly tight expectations and you will
 | 
						|
                hardly need manual assertions at all.
 | 
						|
            </p>
 | 
						|
        
 | 
						|
        <p><a class="target" name="creation"><h2>Creating mock objects</h2></a></p>
 | 
						|
            <p>
 | 
						|
                In the same way that we create server stubs, all we need is an
 | 
						|
                existing class, say a database connection that looks like this...
 | 
						|
<pre>
 | 
						|
<strong>class DatabaseConnection {
 | 
						|
    function DatabaseConnection() {
 | 
						|
    }
 | 
						|
    
 | 
						|
    function query() {
 | 
						|
    }
 | 
						|
    
 | 
						|
    function selectQuery() {
 | 
						|
    }
 | 
						|
}</strong>
 | 
						|
</pre>
 | 
						|
                The class does not need to have been implemented yet.
 | 
						|
                To create a mock version of the class we need to include the
 | 
						|
                mock object library and run the generator...
 | 
						|
<pre>
 | 
						|
<strong>require_once('simpletest/unit_tester.php');
 | 
						|
require_once('simpletest/mock_objects.php');
 | 
						|
require_once('database_connection.php');
 | 
						|
 | 
						|
Mock::generate('DatabaseConnection');</strong>
 | 
						|
</pre>
 | 
						|
                This generates a clone class called
 | 
						|
                <span class="new_code">MockDatabaseConnection</span>.
 | 
						|
                We can now create instances of the new class within
 | 
						|
                our test case...
 | 
						|
<pre>
 | 
						|
require_once('simpletest/unit_tester.php');
 | 
						|
require_once('simpletest/mock_objects.php');
 | 
						|
require_once('database_connection.php');
 | 
						|
 | 
						|
Mock::generate('DatabaseConnection');
 | 
						|
<strong>
 | 
						|
class MyTestCase extends UnitTestCase {
 | 
						|
    
 | 
						|
    function testSomething() {
 | 
						|
        $connection = &new MockDatabaseConnection();
 | 
						|
    }
 | 
						|
}</strong>
 | 
						|
</pre>
 | 
						|
                Unlike the generated stubs the mock constructor needs a reference
 | 
						|
                to the test case so that it can dispatch passes and failures while
 | 
						|
                checking its expectations.
 | 
						|
                This means that mock objects can only be used within test cases.
 | 
						|
                Despite this their extra power means that stubs are hardly ever used
 | 
						|
                if mocks are available.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                <a class="target" name="stub"><h2>Mocks as actors</h2></a>
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                The mock version of a class has all the methods of the original,
 | 
						|
                so that operations like
 | 
						|
                <span class="new_code">$connection->query()</span> are still
 | 
						|
                legal.
 | 
						|
                The return value will be <span class="new_code">null</span>,
 | 
						|
                but we can change that with...
 | 
						|
<pre>
 | 
						|
<strong>$connection->setReturnValue('query', 37)</strong>
 | 
						|
</pre>
 | 
						|
                Now every time we call
 | 
						|
                <span class="new_code">$connection->query()</span> we get
 | 
						|
                the result of 37.
 | 
						|
                We can set the return value to anything, say a hash of
 | 
						|
                imaginary database results or a list of persistent objects.
 | 
						|
                Parameters are irrelevant here, we always get the same
 | 
						|
                values back each time once they have been set up this way.
 | 
						|
                That may not sound like a convincing replica of a
 | 
						|
                database connection, but for the half a dozen lines of
 | 
						|
                a test method it is usually all you need.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                We can also add extra methods to the mock when generating it
 | 
						|
                and choose our own class name...
 | 
						|
<pre>
 | 
						|
<strong>Mock::generate('DatabaseConnection', 'MyMockDatabaseConnection', array('setOptions'));</strong>
 | 
						|
</pre>
 | 
						|
                Here the mock will behave as if the <span class="new_code">setOptions()</span>
 | 
						|
                existed in the original class.
 | 
						|
                This is handy if a class has used the PHP <span class="new_code">overload()</span>
 | 
						|
                mechanism to add dynamic methods.
 | 
						|
                You can create a special mock to simulate this situation.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Things aren't always that simple though.
 | 
						|
                One common problem is iterators, where constantly returning
 | 
						|
                the same value could cause an endless loop in the object
 | 
						|
                being tested.
 | 
						|
                For these we need to set up sequences of values.
 | 
						|
                Let's say we have a simple iterator that looks like this...
 | 
						|
<pre>
 | 
						|
class Iterator {
 | 
						|
    function Iterator() {
 | 
						|
    }
 | 
						|
    
 | 
						|
    function next() {
 | 
						|
    }
 | 
						|
}
 | 
						|
</pre>
 | 
						|
                This is about the simplest iterator you could have.
 | 
						|
                Assuming that this iterator only returns text until it
 | 
						|
                reaches the end, when it returns false, we can simulate it
 | 
						|
                with...
 | 
						|
<pre>
 | 
						|
Mock::generate('Iterator');
 | 
						|
 | 
						|
class IteratorTest extends UnitTestCase() {
 | 
						|
    
 | 
						|
    function testASequence() {<strong>
 | 
						|
        $iterator = &new MockIterator();
 | 
						|
        $iterator->setReturnValue('next', false);
 | 
						|
        $iterator->setReturnValueAt(0, 'next', 'First string');
 | 
						|
        $iterator->setReturnValueAt(1, 'next', 'Second string');</strong>
 | 
						|
        ...
 | 
						|
    }
 | 
						|
}
 | 
						|
</pre>
 | 
						|
                When <span class="new_code">next()</span> is called on the
 | 
						|
                mock iterator it will first return "First string",
 | 
						|
                on the second call "Second string" will be returned
 | 
						|
                and on any other call <span class="new_code">false</span> will
 | 
						|
                be returned.
 | 
						|
                The sequenced return values take precedence over the constant
 | 
						|
                return value.
 | 
						|
                The constant one is a kind of default if you like.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Another tricky situation is an overloaded
 | 
						|
                <span class="new_code">get()</span> operation.
 | 
						|
                An example of this is an information holder with name/value pairs.
 | 
						|
                Say we have a configuration class like...
 | 
						|
<pre>
 | 
						|
class Configuration {
 | 
						|
    function Configuration() {
 | 
						|
    }
 | 
						|
    
 | 
						|
    function getValue($key) {
 | 
						|
    }
 | 
						|
}
 | 
						|
</pre>
 | 
						|
                This is a classic situation for using mock objects as
 | 
						|
                actual configuration will vary from machine to machine,
 | 
						|
                hardly helping the reliability of our tests if we use it
 | 
						|
                directly.
 | 
						|
                The problem though is that all the data comes through the
 | 
						|
                <span class="new_code">getValue()</span> method and yet
 | 
						|
                we want different results for different keys.
 | 
						|
                Luckily the mocks have a filter system...
 | 
						|
<pre>
 | 
						|
<strong>$config = &new MockConfiguration();
 | 
						|
$config->setReturnValue('getValue', 'primary', array('db_host'));
 | 
						|
$config->setReturnValue('getValue', 'admin', array('db_user'));
 | 
						|
$config->setReturnValue('getValue', 'secret', array('db_password'));</strong>
 | 
						|
</pre>
 | 
						|
                The extra parameter is a list of arguments to attempt
 | 
						|
                to match.
 | 
						|
                In this case we are trying to match only one argument which
 | 
						|
                is the look up key.
 | 
						|
                Now when the mock object has the
 | 
						|
                <span class="new_code">getValue()</span> method invoked
 | 
						|
                like this...
 | 
						|
<pre>
 | 
						|
$config->getValue('db_user')
 | 
						|
</pre>
 | 
						|
                ...it will return "admin".
 | 
						|
                It finds this by attempting to match the calling arguments
 | 
						|
                to its list of returns one after another until
 | 
						|
                a complete match is found.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                You can set a default argument argument like so...
 | 
						|
<pre><strong>
 | 
						|
$config->setReturnValue('getValue', false, array('*'));</strong>
 | 
						|
</pre>
 | 
						|
                This is not the same as setting the return value without
 | 
						|
                any argument requirements like this...
 | 
						|
<pre><strong>
 | 
						|
$config->setReturnValue('getValue', false);</strong>
 | 
						|
</pre>
 | 
						|
                In the first case it will accept any single argument,
 | 
						|
                but exactly one is required.
 | 
						|
                In the second case any number of arguments will do and
 | 
						|
                it acts as a catchall after all other matches.
 | 
						|
                Note that if we add further single parameter options after
 | 
						|
                the wildcard in the first case, they will be ignored as the wildcard
 | 
						|
                will match first.
 | 
						|
                With complex parameter lists the ordering could be important
 | 
						|
                or else desired matches could be masked by earlier wildcard
 | 
						|
                ones.
 | 
						|
                Declare the most specific matches first if you are not sure.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                There are times when you want a specific object to be
 | 
						|
                dished out by the mock rather than a copy.
 | 
						|
                The PHP4 copy semantics force us to use a different method
 | 
						|
                for this.
 | 
						|
                You might be simulating a container for example...
 | 
						|
<pre>
 | 
						|
class Thing {
 | 
						|
}
 | 
						|
 | 
						|
class Vector {
 | 
						|
    function Vector() {
 | 
						|
    }
 | 
						|
    
 | 
						|
    function get($index) {
 | 
						|
    }
 | 
						|
}
 | 
						|
</pre>
 | 
						|
                In this case you can set a reference into the mock's
 | 
						|
                return list...
 | 
						|
<pre>
 | 
						|
$thing = &new Thing();<strong>
 | 
						|
$vector = &new MockVector();
 | 
						|
$vector->setReturnReference('get', $thing, array(12));</strong>
 | 
						|
</pre>
 | 
						|
                With this arrangement you know that every time
 | 
						|
                <span class="new_code">$vector->get(12)</span> is
 | 
						|
                called it will return the same
 | 
						|
                <span class="new_code">$thing</span> each time.
 | 
						|
                This is compatible with PHP5 as well.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                These three factors, timing, parameters and whether to copy,
 | 
						|
                can be combined orthogonally.
 | 
						|
                For example...
 | 
						|
<pre>
 | 
						|
$complex = &new MockComplexThing();
 | 
						|
$stuff = &new Stuff();<strong>
 | 
						|
$complex->setReturnReferenceAt(3, 'get', $stuff, array('*', 1));</strong>
 | 
						|
</pre>
 | 
						|
                This will return the <span class="new_code">$stuff</span> only on the third
 | 
						|
                call and only if two parameters were set the second of
 | 
						|
                which must be the integer 1.
 | 
						|
                That should cover most simple prototyping situations.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                A final tricky case is one object creating another, known
 | 
						|
                as a factory pattern.
 | 
						|
                Suppose that on a successful query to our imaginary
 | 
						|
                database, a result set is returned as an iterator with
 | 
						|
                each call to <span class="new_code">next()</span> giving
 | 
						|
                one row until false.
 | 
						|
                This sounds like a simulation nightmare, but in fact it can all
 | 
						|
                be mocked using the mechanics above.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Here's how...
 | 
						|
<pre>
 | 
						|
Mock::generate('DatabaseConnection');
 | 
						|
Mock::generate('ResultIterator');
 | 
						|
 | 
						|
class DatabaseTest extends UnitTestCase {
 | 
						|
    
 | 
						|
    function testUserFinder() {<strong>
 | 
						|
        $result = &new MockResultIterator();
 | 
						|
        $result->setReturnValue('next', false);
 | 
						|
        $result->setReturnValueAt(0, 'next', array(1, 'tom'));
 | 
						|
        $result->setReturnValueAt(1, 'next', array(3, 'dick'));
 | 
						|
        $result->setReturnValueAt(2, 'next', array(6, 'harry'));
 | 
						|
        
 | 
						|
        $connection = &new MockDatabaseConnection();
 | 
						|
        $connection->setReturnValue('query', false);
 | 
						|
        $connection->setReturnReference(
 | 
						|
                'query',
 | 
						|
                $result,
 | 
						|
                array('select id, name from users'));</strong>
 | 
						|
                
 | 
						|
        $finder = &new UserFinder($connection);
 | 
						|
        $this->assertIdentical(
 | 
						|
                $finder->findNames(),
 | 
						|
                array('tom', 'dick', 'harry'));
 | 
						|
    }
 | 
						|
}
 | 
						|
</pre>
 | 
						|
                Now only if our
 | 
						|
                <span class="new_code">$connection</span> is called with the correct
 | 
						|
                <span class="new_code">query()</span> will the
 | 
						|
                <span class="new_code">$result</span> be returned that is
 | 
						|
                itself exhausted after the third call to <span class="new_code">next()</span>.
 | 
						|
                This should be enough
 | 
						|
                information for our <span class="new_code">UserFinder</span> class,
 | 
						|
                the class actually
 | 
						|
                being tested here, to come up with goods.
 | 
						|
                A very precise test and not a real database in sight.
 | 
						|
            </p>
 | 
						|
        
 | 
						|
        <p><a class="target" name="expectations"><h2>Mocks as critics</h2></a></p>
 | 
						|
            <p>
 | 
						|
                Although the server stubs approach insulates your tests from
 | 
						|
                real world disruption, it is only half the benefit.
 | 
						|
                You can have the class under test receiving the required
 | 
						|
                messages, but is your new class sending correct ones?
 | 
						|
                Testing this can get messy without a mock objects library.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                By way of example, suppose we have a
 | 
						|
                <span class="new_code">SessionPool</span> class that we
 | 
						|
                want to add logging to.
 | 
						|
                Rather than grow the original class into something more
 | 
						|
                complicated, we want to add this behaviour with a decorator (GOF).
 | 
						|
                The <span class="new_code">SessionPool</span> code currently looks
 | 
						|
                like this...
 | 
						|
<pre>
 | 
						|
<strong>class SessionPool {
 | 
						|
    function SessionPool() {
 | 
						|
        ...
 | 
						|
    }
 | 
						|
    
 | 
						|
    function &findSession($cookie) {
 | 
						|
        ...
 | 
						|
    }
 | 
						|
    ...
 | 
						|
}
 | 
						|
 | 
						|
class Session {
 | 
						|
    ...
 | 
						|
}</strong>
 | 
						|
</pre>
 | 
						|
                While our logging code looks like this...
 | 
						|
<pre>
 | 
						|
<strong>
 | 
						|
class Log {
 | 
						|
    function Log() {
 | 
						|
        ...
 | 
						|
    }
 | 
						|
    
 | 
						|
    function message() {
 | 
						|
        ...
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class LoggingSessionPool {
 | 
						|
    function LoggingSessionPool(&$session_pool, &$log) {
 | 
						|
        ...
 | 
						|
    }
 | 
						|
    
 | 
						|
    function &findSession($cookie) {
 | 
						|
        ...
 | 
						|
    }
 | 
						|
    ...
 | 
						|
}</strong>
 | 
						|
</pre>
 | 
						|
                Out of all of this, the only class we want to test here
 | 
						|
                is the <span class="new_code">LoggingSessionPool</span>.
 | 
						|
                In particular we would like to check that the
 | 
						|
                <span class="new_code">findSession()</span> method is
 | 
						|
                called with the correct session ID in the cookie and that
 | 
						|
                it sent the message "Starting session $cookie"
 | 
						|
                to the logger.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Despite the fact that we are testing only a few lines of
 | 
						|
                production code, here is what we would have to do in a
 | 
						|
                conventional test case:
 | 
						|
                <ol>
 | 
						|
                    <li>Create a log object.</li>
 | 
						|
                    <li>Set a directory to place the log file.</li>
 | 
						|
                    <li>Set the directory permissions so we can write the log.</li>
 | 
						|
                    <li>Create a <span class="new_code">SessionPool</span> object.</li>
 | 
						|
                    <li>Hand start a session, which probably does lot's of things.</li>
 | 
						|
                    <li>Invoke <span class="new_code">findSession()</span>.</li>
 | 
						|
                    <li>Read the new Session ID (hope there is an accessor!).</li>
 | 
						|
                    <li>Raise a test assertion to confirm that the ID matches the cookie.</li>
 | 
						|
                    <li>Read the last line of the log file.</li>
 | 
						|
                    <li>Pattern match out the extra logging timestamps, etc.</li>
 | 
						|
                    <li>Assert that the session message is contained in the text.</li>
 | 
						|
                </ol>
 | 
						|
                It is hardly surprising that developers hate writing tests
 | 
						|
                when they are this much drudgery.
 | 
						|
                To make things worse, every time the logging format changes or
 | 
						|
                the method of creating new sessions changes, we have to rewrite
 | 
						|
                parts of this test even though this test does not officially
 | 
						|
                test those parts of the system.
 | 
						|
                We are creating headaches for the writers of these other classes.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Instead, here is the complete test method using mock object magic...
 | 
						|
<pre>
 | 
						|
Mock::generate('Session');
 | 
						|
Mock::generate('SessionPool');
 | 
						|
Mock::generate('Log');
 | 
						|
 | 
						|
class LoggingSessionPoolTest extends UnitTestCase {
 | 
						|
    ...
 | 
						|
    function testFindSessionLogging() {<strong>
 | 
						|
        $session = &new MockSession();
 | 
						|
        $pool = &new MockSessionPool();
 | 
						|
        $pool->setReturnReference('findSession', $session);
 | 
						|
        $pool->expectOnce('findSession', array('abc'));
 | 
						|
        
 | 
						|
        $log = &new MockLog();
 | 
						|
        $log->expectOnce('message', array('Starting session abc'));
 | 
						|
        
 | 
						|
        $logging_pool = &new LoggingSessionPool($pool, $log);
 | 
						|
        $this->assertReference($logging_pool->findSession('abc'), $session);</strong>
 | 
						|
    }
 | 
						|
}
 | 
						|
</pre>
 | 
						|
                We start by creating a dummy session.
 | 
						|
                We don't have to be too fussy about this as the check
 | 
						|
                for which session we want is done elsewhere.
 | 
						|
                We only need to check that it was the same one that came
 | 
						|
                from the session pool.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                <span class="new_code">findSession()</span> is a factory
 | 
						|
                method the simulation of which is described <a href="#stub">above</a>.
 | 
						|
                The point of departure comes with the first
 | 
						|
                <span class="new_code">expectOnce()</span> call.
 | 
						|
                This line states that whenever
 | 
						|
                <span class="new_code">findSession()</span> is invoked on the
 | 
						|
                mock, it will test the incoming arguments.
 | 
						|
                If it receives the single argument of a string "abc"
 | 
						|
                then a test pass is sent to the unit tester, otherwise a fail is
 | 
						|
                generated.
 | 
						|
                This was the part where we checked that the right session was asked for.
 | 
						|
                The argument list follows the same format as the one for setting
 | 
						|
                return values.
 | 
						|
                You can have wildcards and sequences and the order of
 | 
						|
                evaluation is the same.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                We use the same pattern to set up the mock logger.
 | 
						|
                We tell it that it should have
 | 
						|
                <span class="new_code">message()</span> invoked
 | 
						|
                once only with the argument "Starting session abc".
 | 
						|
                By testing the calling arguments, rather than the logger output,
 | 
						|
                we insulate the test from any display changes in the logger.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                We start to run our tests when we create the new
 | 
						|
                <span class="new_code">LoggingSessionPool</span> and feed
 | 
						|
                it our preset mock objects.
 | 
						|
                Everything is now under our control.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                This is still quite a bit of test code, but the code is very
 | 
						|
                strict.
 | 
						|
                If it still seems rather daunting there is a lot less of it
 | 
						|
                than if we tried this without mocks and this particular test,
 | 
						|
                interactions rather than output, is always more work to set
 | 
						|
                up.
 | 
						|
                More often you will be testing more complex situations without
 | 
						|
                needing this level or precision.
 | 
						|
                Also some of this can be refactored into a test case
 | 
						|
                <span class="new_code">setUp()</span> method.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Here is the full list of expectations you can set on a mock object
 | 
						|
                in <a href="http://www.lastcraft.com/simple_test.php">SimpleTest</a>...
 | 
						|
                <table>
 | 
						|
<thead>
 | 
						|
                    <tr>
 | 
						|
<th>Expectation</th>
 | 
						|
<th>Needs <span class="new_code">tally()</span>
 | 
						|
</th>
 | 
						|
</tr>
 | 
						|
                    </thead>
 | 
						|
<tbody>
 | 
						|
<tr>
 | 
						|
                        <td><span class="new_code">expect($method, $args)</span></td>
 | 
						|
                        <td style="text-align: center">No</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectAt($timing, $method, $args)</span></td>
 | 
						|
                        <td style="text-align: center">No</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectCallCount($method, $count)</span></td>
 | 
						|
                        <td style="text-align: center">Yes</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectMaximumCallCount($method, $count)</span></td>
 | 
						|
                        <td style="text-align: center">No</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectMinimumCallCount($method, $count)</span></td>
 | 
						|
                        <td style="text-align: center">Yes</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectNever($method)</span></td>
 | 
						|
                        <td style="text-align: center">No</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectOnce($method, $args)</span></td>
 | 
						|
                        <td style="text-align: center">Yes</td>
 | 
						|
                    </tr>
 | 
						|
                    <tr>
 | 
						|
                        <td><span class="new_code">expectAtLeastOnce($method, $args)</span></td>
 | 
						|
                        <td style="text-align: center">Yes</td>
 | 
						|
                    </tr>
 | 
						|
                </tbody>
 | 
						|
</table>
 | 
						|
                Where the parameters are...
 | 
						|
                <dl>
 | 
						|
                    <dt class="new_code">$method</dt>
 | 
						|
                    <dd>The method name, as a string, to apply the condition to.</dd>
 | 
						|
                    <dt class="new_code">$args</dt>
 | 
						|
                    <dd>
 | 
						|
                        The arguments as a list. Wildcards can be included in the same
 | 
						|
                        manner as for <span class="new_code">setReturn()</span>.
 | 
						|
                        This argument is optional for <span class="new_code">expectOnce()</span>
 | 
						|
                        and <span class="new_code">expectAtLeastOnce()</span>.
 | 
						|
                    </dd>
 | 
						|
                    <dt class="new_code">$timing</dt>
 | 
						|
                    <dd>
 | 
						|
                        The only point in time to test the condition.
 | 
						|
                        The first call starts at zero.
 | 
						|
                    </dd>
 | 
						|
                    <dt class="new_code">$count</dt>
 | 
						|
                    <dd>The number of calls expected.</dd>
 | 
						|
                </dl>
 | 
						|
                The method <span class="new_code">expectMaximumCallCount()</span>
 | 
						|
                is slightly different in that it will only ever generate a failure.
 | 
						|
                It is silent if the limit is never reached.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Also if you have juste one call in your test, make sure you're using
 | 
						|
                <span class="new_code">expectOnce</span>.<br>
 | 
						|
                Using <span class="new_code">$mocked->expectAt(0, 'method', 'args);</span>
 | 
						|
                on its own will not be catched :
 | 
						|
                checking the arguments and the overall call count
 | 
						|
                are currently independant.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Like the assertions within test cases, all of the expectations
 | 
						|
                can take a message override as an extra parameter.
 | 
						|
                Also the original failure message can be embedded in the output
 | 
						|
                as "%s".
 | 
						|
            </p>
 | 
						|
        
 | 
						|
        <p><a class="target" name="approaches"><h2>Other approaches</h2></a></p>
 | 
						|
            <p>
 | 
						|
                There are three approaches to creating mocks including the one
 | 
						|
                that SimpleTest employs.
 | 
						|
                Coding them by hand using a base class, generating them to
 | 
						|
                a file and dynamically generating them on the fly.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Mock objects generated with <a href="simple_test.html">SimpleTest</a>
 | 
						|
                are dynamic.
 | 
						|
                They are created at run time in memory, using
 | 
						|
                <span class="new_code">eval()</span>, rather than written
 | 
						|
                out to a file.
 | 
						|
                This makes the mocks easy to create, a one liner,
 | 
						|
                especially compared with hand
 | 
						|
                crafting them in a parallel class hierarchy.
 | 
						|
                The problem is that the behaviour is usually set up in the tests
 | 
						|
                themselves.
 | 
						|
                If the original objects change the mock versions
 | 
						|
                that the tests rely on can get out of sync.
 | 
						|
                This can happen with the parallel hierarchy approach as well,
 | 
						|
                but is far more quickly detected.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                The solution, of course, is to add some real integration
 | 
						|
                tests.
 | 
						|
                You don't need very many and the convenience gained
 | 
						|
                from the mocks more than outweighs the small amount of
 | 
						|
                extra testing.
 | 
						|
                You cannot trust code that was only tested with mocks.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                If you are still determined to build static libraries of mocks
 | 
						|
                because you want to simulate very specific behaviour, you can
 | 
						|
                achieve the same effect using the SimpleTest class generator.
 | 
						|
                In your library file, say <em>mocks/connection.php</em> for a
 | 
						|
                database connection, create a mock and inherit to override
 | 
						|
                special methods or add presets...
 | 
						|
<pre>
 | 
						|
<?php
 | 
						|
    require_once('simpletest/mock_objects.php');
 | 
						|
    require_once('../classes/connection.php');
 | 
						|
<strong>
 | 
						|
    Mock::generate('Connection', 'BasicMockConnection');
 | 
						|
    class MockConnection extends BasicMockConnection {
 | 
						|
        function MockConnection() {
 | 
						|
            $this->BasicMockConnection();
 | 
						|
            $this->setReturn('query', false);
 | 
						|
        }
 | 
						|
    }</strong>
 | 
						|
?>
 | 
						|
</pre>
 | 
						|
                The generate call tells the class generator to create
 | 
						|
                a class called <span class="new_code">BasicMockConnection</span>
 | 
						|
                rather than the usual <span class="new_code">MockConnection</span>.
 | 
						|
                We then inherit from this to get our version of
 | 
						|
                <span class="new_code">MockConnection</span>.
 | 
						|
                By intercepting in this way we can add behaviour, here setting
 | 
						|
                the default value of <span class="new_code">query()</span> to be false.
 | 
						|
                By using the default name we make sure that the mock class
 | 
						|
                generator will not recreate a different one when invoked elsewhere in the
 | 
						|
                tests.
 | 
						|
                It never creates a class if it already exists.
 | 
						|
                As long as the above file is included first then all tests
 | 
						|
                that generated <span class="new_code">MockConnection</span> should
 | 
						|
                now be using our one instead.
 | 
						|
                If we don't get the order right and the mock library
 | 
						|
                creates one first then the class creation will simply fail.
 | 
						|
            </p>
 | 
						|
            <p>
 | 
						|
                Use this trick if you find you have a lot of common mock behaviour
 | 
						|
                or you are getting frequent integration problems at later
 | 
						|
                stages of testing.
 | 
						|
            </p>
 | 
						|
        
 | 
						|
    </div>
 | 
						|
        References and related information...
 | 
						|
        <ul>
 | 
						|
<li>
 | 
						|
            The original
 | 
						|
            <a href="http://www.mockobjects.com/">Mock objects</a> paper.
 | 
						|
        </li>
 | 
						|
<li>
 | 
						|
            SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
 | 
						|
        </li>
 | 
						|
<li>
 | 
						|
            SimpleTest home page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
 | 
						|
        </li>
 | 
						|
</ul>
 | 
						|
<div class="menu_back"><div class="menu">
 | 
						|
<a href="index.html">SimpleTest</a>
 | 
						|
                |
 | 
						|
                <a href="overview.html">Overview</a>
 | 
						|
                |
 | 
						|
                <a href="unit_test_documentation.html">Unit tester</a>
 | 
						|
                |
 | 
						|
                <a href="group_test_documentation.html">Group tests</a>
 | 
						|
                |
 | 
						|
                <span class="chosen">Mock objects</span>
 | 
						|
                |
 | 
						|
                <a href="partial_mocks_documentation.html">Partial mocks</a>
 | 
						|
                |
 | 
						|
                <a href="reporter_documentation.html">Reporting</a>
 | 
						|
                |
 | 
						|
                <a href="expectation_documentation.html">Expectations</a>
 | 
						|
                |
 | 
						|
                <a href="web_tester_documentation.html">Web tester</a>
 | 
						|
                |
 | 
						|
                <a href="form_testing_documentation.html">Testing forms</a>
 | 
						|
                |
 | 
						|
                <a href="authentication_documentation.html">Authentication</a>
 | 
						|
                |
 | 
						|
                <a href="browser_documentation.html">Scriptable browser</a>
 | 
						|
</div></div>
 | 
						|
<div class="copyright">
 | 
						|
            Copyright<br>Marcus Baker 2006
 | 
						|
        </div>
 | 
						|
</body>
 | 
						|
</html>
 |