So I am not sure what I am doing wrong but:
class Details {
public function details($href) {
$client = new Client();
$eveLog = new EveLogHandler();
$response = $client->request('GET', $href);
$eveLog->requestLog($response, 'eveonline_item_details.log');
if ($response->getStatusCode() === 200) {
return json_decode($response->getBody()->getContents());
}
return false;
}
}
I want to mock this: $eveLog->requestLog($response, 'eveonline_item_details.log');
So I wrote a test:
class DetailsTest extends \PHPUnit_Framework_TestCase {
public function getLogMock() {
return $this->getMockBuilder('EveOnline\Logging\EveLogHandler')
->setMethods(['requestLog'])
->getMock();
}
public function testDetailsDoesNotReturnFalse() {
$details = new EveOnline\Items\Details();
$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
->method('requestLog')
->with('request', 'request.log');
$response = $details->details('http://example.com');
$this->assertNotFalse($response);
}
}
Accept it doesnt mock the method call, instead it freaks out with an error:
1) DetailsTest::testDetailsDoesNotReturnFalse
Error: Call to undefined function EveOnline\Logging\storage_path()
Now this method: storage_path
is a laravel method and since this library is out side of laravel, for development purposes, the method doesn't exist, hence me trying to mock the call to: $eveLog->requestLog($response, 'eveonline_item_details.log');
Two questions arise from this:
storage_path
method.Ideas?
update
It should be known that this class gets turned into a laravel facade via a provider class and a facade class that both get registered with laravel allowing me to do something like
EveDetails::details()
For example. Learn more here https://laravel.com/docs/5.1/facades
I can post the facade and provider class of that will help.
The only reason the class is instantiated in my ear is because this particular component is being built as a separate installable component of laravel.
Your method Details::details()
doesn't know that $eveLog
should be an instance of your mock instead of class EveLogHandler
. You have to inject the instance of your logger by using dependency injection.
The simpliest way to do this is to put it to the constructor:
class Details {
private $eveLog;
public function __construct($eveLog) {
$this->eveLog = $eveLog;
}
public function details($href) {
$client = new Client();
$response = $client->request('GET', $href);
$this->eveLog->requestLog($response, 'eveonline_item_details.log');
if ($response->getStatusCode() === 200) {
return json_decode($response->getBody()->getContents());
}
return false;
}
}
In your production code you'll have to call:
$details = new EveOnline\Items\Details(new EveLogHandler());
to inject the real Eventlogger (an instance of class EveLogHandler
) to the instance of class Details
.
In your TestCase you'll now have inject your mock:
$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
->method('requestLog')
->with('request', 'request.log');
$details = new EveOnline\Items\Details($logger);