6/15/2014 - 1:02 PM

Basic PHPUnit Notes

Basic PHPUnit Notes

A few gard won lessons!

1. You cannot set expectations on a non-mocked method
2. Don't use multiple mocks of the same class and then inject these into another mock
3. When using at, this applies at an object level, not method
4. When using at, any mocked methods will be expected in the ordering

  - Standard use (consumes phpunit.xml.dist)

phpunit --coverage-text
  - Given coverage info in cli
phpunit --coverage-html <directory>
  - As above but creates coverage report in provided directory

phpunit -c <file>
  - Use given config file


class RemoteConnectTest extends PHPUnit_Framework_TestCase
	- Makes test methods available

public function setUp(){ }
	- Will be run before every test

public function tearDown(){ }
	- Will be run after every test

(all using $this-><method>)

assertInstanceOf(<constraint>, <actual>)
	- Passes if actual is of type constraint
assertEquals(<constraint>, <actual>
	- Passes if actual is equal to constraint

assertClassHasStaticAttribute(<constraint>, <class>)
	- Passes if class has static attribute with name constraint
	- Passes if file exists
	- Pass if method echos / prints string

assertArrayHasKey(<constraint>, <actual>)
	- Passes if actual array has element with key constraint

	- Passes if actual evaluates to true
	- Passes if actual evaluates to false


assertGreaterThan(<constraint>, <actual>)
	- Passes if actual is greater than constraint
assertLessThan(<constraint>, <actual>)
	- Passes if actual is less than constraint


	- Make class have dependancy injected
	- This can than be replaced with mock
	- Set to return values for called methods

Other Functions
(all using $this-><method>)

	- Signal test failure with message
(Set in doc block above test method)

@expectedException <exceptionType>
	- Passes if method throws exception of given type
General Notes
- One assertion per test?
- Allows refactoring to be re-tested to ensure to functionality not broken
- TDD = Write test, write code that passes test, repeat in small iterative cycles
- Promoted "keep it simple stupid" (KISS) and "You aren't gonna need it" (YAGNI)

Installation Through Pear
Install Pear
	sudo php -d detect_unicode=0 go-pear.phar
Install PHPUnit
	pear channel-discover
	pear install --alldeps
(Remember to add pear to PATH var)

Installation Through Composer
(There is no offical version of PHPUnit on packagist, use unofficial)
Install Composer (locally)
	curl -sS | php
	(move to bin dir (e.g. /usr/bin) to make composer command globally available)
Installing PHPUnit for project
	Create JSON file in root (composer.json) Example (with optional php v require):
		"require" : {
			"php" : "version",
			"EHER/PHPUnit": "1.6"
	composer install
PHPUnit converts errors into exceptions
- Can use something like the below code to tesk for errors instead
- Sets customer error handler which stored error details in array
- Defined assertion that an error has occured by checking the array
class MyTest extends PHPUnit_Framework_TestCase
    private $errors;
    protected function setUp() {
        $this->errors = array();
        set_error_handler(array($this, "errorHandler"));
    public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
        $this->errors[] = compact("errno", "errstr", "errfile",
            "errline", "errcontext");
    public function assertError($errstr, $errno) {
        foreach ($this->errors as $error) {
            if ($error["errstr"] === $errstr
                && $error["errno"] === $errno) {
        $this->fail("Error with level " . $errno .
            " and message '" . $errstr . "' not found in ", 
            var_export($this->errors, TRUE));
    public function testDoStuff() {
        // execute code that triggers a warning
        $this->assertError("Message for the expected error",

Passing an array as subsequest returns on a mocked method:
->will(new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($returnValueArray));