Reputation: 14548
my application has a logger library with the signature:
final class Logger {
public static method debug($msg);
public static method warn($msg);
public static method error($msg);
}
the class i want to test, another global static helper, use it as
final class TestMe {
public static method TestThis(){
Logger::debug('TestThis() called');
doThings();
}
}
How to test the TestMe
class by mocking the Logger
one and waiting for the expected messages?
Upvotes: 1
Views: 4593
Reputation: 43700
Your Logger class cannot be mocked by PHPUnit for a couple of reasons.
final
which means that it cannot be extended. When PHPUnit creates a mock of an object, it creates a new object that extends the class being mocked. The final
keyword prevents extending a class, so a mock cannot be created.http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
You have two options for testing things like this:
Logger
class is doing gets done. This will make any tests less of a "unit" test but they do encapsulate the behavior that is expected and can still be useful.mockLogger
that doesn't call the methods statically. This may be more painful but will result in your code more flexible IMO.Upvotes: 4
Reputation: 1170
If you are using a testing framework like PHPUnit, it offers the ability to mock an object. You could create a mock object for your logger class and define the debug method in it.
It is explained in details here :
https://phpunit.de/manual/current/en/test-doubles.html
Here is a little example taken from that page :
<?php
require_once 'SomeClass.php';
class StubTest extends PHPUnit_Framework_TestCase
{
public function testStub()
{
// Create a stub for the SomeClass class.
$stub = $this->getMockBuilder('SomeClass')
->getMock();
// Configure the stub.
$stub->method('doSomething')
->willReturn('foo');
// Calling $stub->doSomething() will now return
// 'foo'.
$this->assertEquals('foo', $stub->doSomething());
}
}
?>
Upvotes: -2