I'm trying to get into the workfow of using phpSpec to desing my classes. I have stumbled on testing a handle method on one of my event handlers.
My spec:
use App\Order;
use App\Models\Payments\Payment;
use App\Services\Payments\PaymentService;
use App\Events\Payments\AccountPayment;
class RecordPaymentTransactionSpec extends ObjectBehavior
{
function let(PaymentService $paymentService)
{
$this->beConstructedWith($paymentService);
}
function it_is_initializable()
{
$this->shouldHaveType('App\Handlers\Events\Payments\RecordPaymentTransaction');
}
function it_should_record_payment_transaction(AccountPayment $event)
{
$this->paymentService->recordPayment($event)->shouldBeCalled();
}
}
And this my implementation:
class RecordPaymentTransaction {
public $paymentService;
/**
* Create the event handler.
*
* RecordPaymentTransaction constructor.
* @param PaymentService $paymentService
*/
public function __construct(PaymentService $paymentService)
{
$this->paymentService = $paymentService;
}
/**
* Handle the event.
*
* @param AccountPayment $event
* @return void
*/
public function handle(AccountPayment $event)
{
$this->paymentService->recordPayment($event);
}
}
However, I keep getting this error:
- it should record payment transaction
no beCalled([array:0]) matcher found for null.
Cannot see what I'm doing wrong here, help please.
function it_should_record_payment_transaction(AccountPayment $event)
{
$this->paymentService->recordPayment($event)->shouldBeCalled();
}
should be
function it_should_record_payment_transaction(
PaymentService $paymentService,
AccountPayment $event
) {
$paymentService->recordPayment($event)->shouldBeCalled();
$this->handle($event);
}
or
function it_should_record_payment_transaction(AccountPayment $event)
{
$prophet = new Prophet();
$paymentService = $prophet->prophesize(PaymentService::class);
$paymentService->recordPayment($event)->shouldBeCalled();
$this->handle($event);
$prophet->checkPredictions();
}
This is because, when you spec a class, you should only call a public method of it and make expectations on collaborators.
You don't need to (and you are not supposed to do) call collaborators with
$this->collaboratorName->method->shouldBeCalled()
Use "implicit" mocks (by passing them into spec method signature: if they are used in let
function and have same name and type, they are the same mock for phpspec) or "explicit" mocks that you can obtain by calling prophesize
on Prophet
object. The only difference between them is that "implicit" mocks are checked automatically whereas "explicit" ones need to be checked manually ($prophet->checkPredictions();
)