PHP unit failure testing - php

I have to test this class for failure condition
<?php
namespace Gpx\Handlers;
use Gpx\EntityInfrastructure\Model\Events\PlatformSessionInitiated;
use Gpx\EntityInfrastructure\Model\Payload;
use Gpx\Hfx\Framework\MessageTransportApplication\Handler\SynchronousHandlerInterface;
use Gpx\Hfx\Framework\MessageTransportApplication\Handler\MessageHandlingContextInterface;
use Gpx\HfxEventSourcing\HfxAggregateRoot;
use Gpx\HfxEventSourcing\HfxEventMetadata;
use Gpx\HfxEventSourcing\HfxProjectionHelper;
use Gpx\HfxEventSourcing\HfxRepository;
use Gpx\Hfx\MessageTransport\Response\SendableResponse;
use Gpx\Exceptions\IdNotDefinedException;
use Gpx\Exceptions\AggregateNotFoundException;
class BroadcastPlatformSessionInitiated implements SynchronousHandlerInterface
{
/** #var HfxRepository */
private $repository;
/** #var HfxProjectionHelper */
private $projectionHelper;
public function __construct(HfxRepository $repository, HfxProjectionHelper $projectionHelper)
{
$this->repository = $repository;
$this->projectionHelper = $projectionHelper;
}
/*
* #param MessageHandlingContextInterface $context
* #return SendableResponse
*/
public function handleSynchronousMessage(MessageHandlingContextInterface $context): SendableResponse
{
try {
$content = $context->message();
$header = $context->rawMessage()->header();
$metadata = HfxEventMetadata::fromHfxHeader($header);
$payload = Payload::fromMessageContent($content);
$roleAggregate = HfxAggregateRoot::createEntityFromEvent(PlatformSessionInitiated::class, $payload, $metadata);
$this->repository->save($roleAggregate);
$currentEvent = $roleAggregate->currentEvent();
$context->sendNonBlockingAsynchronous('platform_session_initiated', $currentEvent);
$this->projectionHelper->updateReadModel(HfxAggregateRoot::class);
return SendableResponse::answerTo($context->rawMessage(), 1000, [
'responseMessage' => 'Success',
'event' => $currentEvent
]);
} catch (IdNotDefinedException $e) {
return SendableResponse::answerTo($context->rawMessage(), 2000, [
'responseMessage' => 'Failure. Session Id is not defined.'
]);
}
}
}
Following is the test case I have written
<?php
namespace Gpx\Tests\Handlers;
use Ramsey\Uuid\Uuid;
use Gpx\Json\JsonEncode;
use Prophecy\Argument;
use PHPUnit\Framework\TestCase;
use Gpx\HfxEventSourcing\HfxProjectionHelper;
use Gpx\HfxEventSourcing\HfxRepository;
use Gpx\Hfx\Framework\MessageTransportApplication\Handler\MessageHandlingContextInterface;
use Gpx\Handlers\BroadcastPlatformSessionInitiated;
use Gpx\Hfx\MessageTransport\Message\ReceivedMessage;
use Gpx\Exceptions\IdNotDefinedException;
class BroadcastPlatformSessionInitiatedTest extends TestCase
{
/** #var HfxRepository */
private $repository;
/** #var HfxProjectionHelper */
private $projectionHelper;
/** #var MessageHandlingContext */
private $context;
/**
* This will run before each test
*/
public function setUp()
{
// Expected return value of message() function of $this->context
$expectedReturnValue = [
"session_id" => "1a92-4376-a8eb-deaf208ssess11",
"user_id" => "we",
"access_jwt" => "C",
"access_token" => "john#gmail.com",
"refresh_token" => "C",
"refresh_token_expires" => "john#gmail.com"
];
// Expected return value of rawMessage() function of $this->context
$headerResponseExpected = [
'header' => [
'version' => '2.0',
'originId' => (string)Uuid::uuid4(),
'destination' => 'application/meta#1.0.0',
'sent' => '2017-12-19T10:12:37.941+00:00'
],
'content' => [
'session_id' => null,
'title' => "A task's title."
]
];
// Prediction of $this->context object starts
$this->context = $this->prophesize(MessageHandlingContextInterface::class);
$this->context->message(Argument::any())->willReturn($expectedReturnValue);
$encodedMessage = new JsonEncode($headerResponseExpected);
$rawMessage = ReceivedMessage::fromEncodedMessage($encodedMessage->asString());
$this->context->rawMessage()->willReturn($rawMessage);
$this->context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))
->shouldBeCalled();
// Prediction of $this->context object ends
}
// We have to test handleSynchronousMessage handler whether it is returning sendable response with certain properties in it.
public function testHandleSynchronousMessageForSuccess()
{
// Prophecy means prediction of the future object
$this->ravenRepository = $this->prophesize(HfxRepository::class);
$this->ravenRepository->save(Argument::any())
->shouldBeCalled();
// Mocking HfxProjectionHelper and calling the method updateReadModel which will return the string UpdateReadModel
$this->projectionHelper = $this->createMock(HfxProjectionHelper::class);
$this->projectionHelper->method('updateReadModel')
->willReturn('UpdateReadModel');
// Actual calling
$broadcastPlatformSessionInitiated = new BroadcastPlatformSessionInitiated($this->ravenRepository->reveal(), $this->projectionHelper);
$response = $broadcastPlatformSessionInitiated->handleSynchronousMessage($this->context->reveal());
$this->assertInstanceOf('Gpx\Hfx\MessageTransport\Response\SendableResponse', $response);
$this->assertArrayHasKey("responseMessage", $response->content()->data());
$this->assertArrayHasKey("event", $response->content()->data());
$this->assertEquals("Success", $response->content()->data()['responseMessage']);
}
// We have to test handleSynchronousMessage handler whether it is returning sendable response with certain properties in it.
public function testHandleSynchronousMessageForFailure()
{
// Expected return value of message() function of $this->context
$expectedReturnValue = [
"session_id" => null,
"user_id" => "we",
"access_jwt" => "C",
"access_token" => "john#gmail.com",
"refresh_token" => "C",
"refresh_token_expires" => "john#gmail.com"
];
// Expected return value of rawMessage() function of $this->context
$headerResponseExpected = [
'header' => [
'version' => '2.0',
'originId' => (string)Uuid::uuid4(),
'destination' => 'application/meta#1.0.0',
'sent' => '2017-12-19T10:12:37.941+00:00'
],
'content' => [
'session_id' => '1a92-4376-a8eb-deaf208ssess11',
'title' => "A task's title."
]
];
// Prediction of $this->context object starts
$this->context = $this->prophesize(MessageHandlingContextInterface::class);
$this->context->message(Argument::any())->willReturn($expectedReturnValue);
$encodedMessage = new JsonEncode($headerResponseExpected);
$rawMessage = ReceivedMessage::fromEncodedMessage($encodedMessage->asString());
$this->context->rawMessage()->willReturn($rawMessage);
$this->context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))->shouldNotBeCalled();
// Prediction of $this->context object ends
// Prophecy means prediction of the future object
$this->ravenRepository = $this->prophesize(HfxRepository::class);
// Mocking HfxProjectionHelper and calling the method updateReadModel which will return the string UpdateReadModel
$this->projectionHelper = $this->createMock(HfxProjectionHelper::class);
$this->projectionHelper->method('updateReadModel')->willReturn('UpdateReadModel');
// Actual calling
$broadcastPlatformSessionInitiated = new BroadcastPlatformSessionInitiated($this->ravenRepository->reveal(), $this->projectionHelper);
$response = $broadcastPlatformSessionInitiated->handleSynchronousMessage($this->context->reveal());
$this->assertInstanceOf('Gpx\Hfx\MessageTransport\Response\SendableResponse', $response);
$this->assertArrayHasKey("responseMessage", $response->content()->data());
$this->assertEquals("Failure. Session Id is not defined.", $response->content()->data()['responseMessage']);
}
}
This is the failure I am getting for testHandleSynchronousMessageForFailure
Gpx\Tests\Handlers\BroadcastPlatformSessionInitiatedTest::testHandleSynchronousMessageForFailure
Some predictions failed:
Double\MessageHandlingContextInterface\P3:
No calls have been made that match:
Double\MessageHandlingContextInterface\P3->sendNonBlockingAsynchronous(exact("platform_session_initiated"), type(array))
but expected at least one.
FAILURES!
Tests: 3, Assertions: 18, Failures: 1.
Could any one please clarify what I am doing wrong here?

Your setUp() method gets called before every test, so testHandleSynchronousMessageForFailure() is also expecting sendNonBlockingAsynchronous() to be called:
$this->context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))
->shouldBeCalled();
Even if you call shouldNotBeCalled() on it in the failure test. So, move the shouldBeCalled() call to the testHandleSynchronousMessageForSuccess(), that way it will expect it to be called in the success test, and not to be called in the failure test.
You should also tell PHPUnit to expect an IdNotDefinedException in the failure test:
$this->expectException(Gpx\Exceptions\IdNotDefinedException::class);

Related

Not able to test the Laravel socialite

I'm trying to perform unit test for Laravel socialite function. There are 2 functions for redirect and callback.
There is one problem that I couldn't test successful was the callback function.
Here is how I test the redirect function
AuthController.php
/**
* #return mixed
*/
public function loginWithGoogle () {
return Socialite::driver('google')
->scopes([
'https://www.googleapis.com/auth/userinfo.email'
])
->with([
'access_type' => 'offline',
'prompt' => 'consent select_account'
])
->redirect();
}
AuthTest.php
public function testGoogleLoginForwardRequest()
{
$response = $this->getJson('/oauths/forward/google');
$response->assertStatus(302);
}
For the callback function
AuthController.php
/**
* #return RedirectResponse
*/
public function loginRedirectFromGoogle (): RedirectResponse
{
$user = Socialite::driver('google')->stateless()->user();
$acUser = User::where('email', $user->getEmail())->first();
if(empty($acUser)){
return redirect('/oauth/login?'.http_build_query([
'force_external_oauth_response' => 'true',
'external_oauth_response_error' => 'User account not register'
]));
}
Auth::login($acUser);
OAuthProvider::updateOrCreate(
[
'provider_name' => 'google',
'provider_id' => $user->id,
'user_id' => $acUser->id
],
[
'encrypted_token' => Crypt::encryptString($user->token),
'encrypted_refreshed_token' => Crypt::encryptString($user->refreshToken),
'expires_at' => time() + $user->expiresIn // time and expiresIn are all in seconds
]
);
return redirect('/oauth/login?'.http_build_query([
'force_external_oauth_response' => 'true',
'external_oauth_response_error' => ''
]));
}
AuthTest.php
public function testGoogleLoginRedirectRequest()
{
Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
$abstractUser = Mockery::mock('Laravel\Socialite\Two\User');
$abstractUser
->shouldReceive('getId')
->andReturn(rand())
->shouldReceive('getName')
->andReturn($this->faker->name())
->shouldReceive('getEmail')
->andReturn($this->faker->name() . '#gmail.com')
->shouldReceive('getAvatar')
->andReturn('https://en.gravatar.com/userimage');
Socialite::shouldReceive('driver')->with('google')->andReturn($abstractUser);
$response = $this->getJson('/oauths/forward/google');
$response->assertStatus(302);
}
For this function it returns error the following
Mockery\Exception\BadMethodCallException: Method Mockery_0_Laravel_Socialite_Two_User::scopes() does not exist on this mock object in C:\xampp\htdocs\ac-dev\achievement-console\vendor\mockery\mockery\library\Mockery\Loader\EvalLoader.php(34) : eval()'d code:928
For the callback function, I followed this example How to Test Laravel Socialite

Laravel test class property not persisting

I'm trying to set a sensorId property that will be used by every method in my feature test. The problem is that it is not persisting between tests.
Here is my test class:
class LogApiPostTest extends TestCase
{
public $sensorId;
public function setUp(): void
{
parent::setUp();
$this->sensorId = 'SEN' . rand(10000000, 999999999);
}
public function test_creates_sensor()
{
$response = $this->post('/api/logs', $this->data([
//
]));
$response->assertStatus(200);
$response->assertSeeText('Sensor created');
}
public function test_updates_sensor()
{
$response = $this->post('/api/logs', $this->data([
//
]));
$response->assertStatus(200);
$response->assertSeeText('Sensor updated');
}
public function test_creates_car()
{
$response = $this->post('/api/logs', $this->data([
'CarID' => 'B',
]));
$response->assertStatus(200);
$response->assertSeeText('Car created');
}
public function test_updates_car()
{
$response = $this->post('/api/logs', $this->data([
'CarID' => 'B',
]));
$response->assertStatus(200);
$response->assertSeeText('Car updated');
}
public function test_is_unauthorized()
{
$response = $this->post('/api/logs', $this->data([
'token_id' => 'thisShouldntWork',
]));
$response->assertUnauthorized();
}
public function data($merge = [])
{
return array_merge([
'token_id' => config('api.token'),
'sensorID' => $this->sensorId,
'CarID' => 'A',
'LogType' => 'CarLog',
'Time' => time(),
'DrctnFlr' => '-02',
'MCSS' => 'STB',
'OpMode' => 'INA',
'DoorStats' => '][**',
'DoorCmd' => 'C6:C1>',
'OCSS' => 'GTN02',
'Load' => '002%',
], $merge);
}
}
I just want the sensorId property to persist for all tests in this class.
When there is a dependency between tests, you must use the #depends annotation.
This allows to ensure the execution order of tests is correct and also to pass values between tests. Instead of making sensorId to persist, just pass it from test to test.
https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html#test-dependencies

How to inject customized info to Google Stackdriver in Laravel log

Hi I'm new to Laravel framework and I'm trying to inject process ID into every log passed to Google Logging service.
I've been able to see the log passed into Google Logging service now, but I've no idea how I could inject more info(Process ID in this case) into my log message.
So far I've tried "tap" method and I can see addition info injected into my log while reading laravel.log file, but same method doesn't seems to work while using Google Cloud Logging plugin.
Below is my script for Google Logging service.
Inside config/logging.php
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['stackdriver'],
],
'stackdriver' => [
'driver' => 'custom',
'via' => App\Logging\CreateStackdriverLogger::class,
'level' => 'debug',
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'tap' => [App\Logging\ProcessorTap::class],
],
];
CreateStackdriverLogger.php
use Google\Cloud\Logging\LoggingClient;
use Monolog\Handler\PsrHandler;
use Monolog\Logger;
class CreateStackdriverLogger
{
/**
* Create a custom Monolog instance.
*
* #param array $config
* #return \Monolog\Logger
*/
public function __invoke(array $config)
{
$logName = isset($config['logName']) ? $config['logName'] : 'app';
$psrLogger = LoggingClient::psrBatchLogger($logName);
$handler = new PsrHandler($psrLogger);
$logger = new Logger($logName, [$handler]);
return $logger;
}
}
Code for 'tap' method, I'm able to see 'pid' inside 'extra', but same method don't work with 'stackdriver'.
ProcessorTab.php
namespace App\Logging;
use Illuminate\Log\Logger;
use Illuminate\Support\Arr;
use Monolog\Formatter\LineFormatter;
class ProcessorTap
{
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->pushProcessor(function ($record) {
return Arr::add($record, 'prefix', getmypid());
});
$handler->setFormatter($this->getLogFormatter());
$handler->pushProcessor([$this, 'processLogRecord']);
}
}
public function processLogRecord(array $record): array
{
$record['extra'] += [
'pid' => getmypid(),
];
return $record;
}
protected function getLogFormatter()
{
$format = "[%datetime%] %channel%.%level_name%: %prefix%.%message% %context% %extra%\n";
return new LineFormatter($format, null, true, true);
}
}

Laravel Tap Formatter: where do I actually format the message?

In my laravel application there's need to format a message I need to send into slack. Hence I set a slack log channel into config/logging.php:
'slack' => [
'driver' => 'slack',
'url' => /*Censored Hook URL*/,
'username' => 'MyApp',
'emoji' => ':gear:',
'level' => 'debug',
],
Also as seen on documentation I can do a monolog formater, hence I did the following:
namespace App\Logging;
class SlackLogFormatter
{
/**
* Customize the given logger instance.
*
* #param \Illuminate\Log\Logger $logger
* #return void
*/
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(...);
}
}
}
And specified it as tap into my log:
'slack' => [
'driver' => 'slack',
'tap' => [App\Logging\SlackLogFormatter::class]
'url' => /*Censored Hook URL*/,
'username' => 'MyApp',
'emoji' => ':gear:',
'level' => 'debug',
],
But in my formater where do I process the log entry itself? I mean:
The $handler->setFormatter does not seem to be a method of \Illuminate\Log\Logger class.
I cannot find out what method I need to override when I need to provide a custom format. I mean I have the invoke method then afterwards what?
Dimitrios is almost right (or perhaps this worked on older versions) but as Xavier said, if you copy that code exactly you will get the error
Return value of Monolog\Handler\AbstractProcessingHandler::processRecord() must be of the type array, null returned
You are going to want to do something like this instead :
<?php
namespace App\Logging;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\SlackWebhookHandler;
use Request;
class CustomiseFormatter
{
protected $request;
public function __construct(Request $request = null)
{
$this->request = $request;
}
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
if ($handler instanceof SlackWebhookHandler) {
$handler->setFormatter(new LineFormatter(
'[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
));
$handler->pushProcessor([$this, 'processLogRecord']);
}
}
}
public function processLogRecord(array $record): array
{
$record['extra'] += [
'url' => env("APP_URL"),
];
return $record;
}
}
Equally, as with how extra has be modified, you can change any other value.
The formatter for slack should be the following:
namespace App\Logging;
use Monolog\Formatter\LineFormatter;
class SlackLogFormatter
{
/**
* Customize the given logger instance.
*
* #param \Illuminate\Log\Logger $logger
* #return void
*/
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
if ($handler instanceof SlackWebhookHandler) {
$format=""; // Look on the Monolog's Line formatter documentation
$formatter= new LineFormatter($format,"Y-m-d H:i:s");
$handler->pushProcessor(function ($record) {
//Append extra info of formatting here
});
$handler->setFormatter($formatter);
}
}
}
}
And config the slack not to send attachment nessesary for the formatter to work:
'slack' => [
'driver' => 'slack',
'tap' => [App\Logging\SlackLogFormatter::class]
'url' => /*Censored Hook URL*/,
'username' => 'MyApp',
'emoji' => ':gear:',
'level' => 'debug',
'attachment' => FALSE,
],
The setFormatter method takes a new Monolog Formatter as seen in: https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#formatters
Also the pushProcessor allows you to populate extra fields on your message eg. Showing an emoji on your log message:
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
if ($handler instanceof SlackWebhookHandler) {
$format="%emoji% %message%";
$formatter= new LineFormatter($format,"Y-m-d H:i:s");
$handler->pushProcessor(function ($record) {
$record['emoji']=":poop:";
});
$handler->setFormatter($formatter);
}
}
}

How to determine why a PHPUnit mock fails?

I want to unit test following class.
<?php
namespace Gpx\Handlers;
use Gpx\EntityInfrastructure\Model\Events\SessionInvalidated;
use Gpx\EntityInfrastructure\Model\Payload;
use Gpx\Hfx\Framework\MessageTransportApplication\Handler\SynchronousHandlerInterface;
use Gpx\Hfx\Framework\MessageTransportApplication\Handler\MessageHandlingContextInterface;
use Gpx\HfxEventSourcing\HfxAggregateRoot;
use Gpx\HfxEventSourcing\HfxProjectionHelper;
use Gpx\HfxEventSourcing\HfxEventMetadata;
use Gpx\HfxEventSourcing\HfxRepository;
use Gpx\Hfx\MessageTransport\Response\SendableResponse;
class BroadcastSessionInvalidated implements SynchronousHandlerInterface
{
/** #var HfxRepository */
private $repository;
/** #var HfxProjectionHelper */
private $projectionHelper;
public function __construct(HfxRepository $repository, HfxProjectionHelper $projectionHelper)
{
$this->repository = $repository;
$this->projectionHelper = $projectionHelper;
}
public function handleSynchronousMessage(MessageHandlingContextInterface $context): SendableResponse
{
$content = $context->message();
$header = $context->rawMessage()->header();
$metadata = HfxEventMetadata::fromHfxHeader($header);
$payload = Payload::fromMessageContent($content);
/** #var HfxAggregateRoot $roleAggregate */
// Gpx\HfxEventSourcing\HfxAggregateRoot
$roleAggregate = $this->repository->get($payload->id());
$roleAggregate->registerEvent(SessionInvalidated::class, $payload, $metadata);
$this->repository->save($roleAggregate);
$currentEvent = $roleAggregate->currentEvent();
$context->sendNonBlockingAsynchronous('session_invalidated',$content);
$this->projectionHelper->updateReadModel();
return SendableResponse::answerTo($context->rawMessage(), 1100, [
'responseMessage' => 'Success',
'event' => $currentEvent
]);
}
}
Test case I have written so far
<?php
namespace Gpx\Tests\Feature;
use Ramsey\Uuid\Uuid;
use Gpx\Json\JsonEncode;
use Prophecy\Argument;
use PHPUnit\Framework\TestCase;
use Gpx\HfxEventSourcing\Hfx;
use Gpx\HfxEventSourcing\HfxRepository;
use Gpx\Hfx\Framework\MessageTransportApplication\Handler\MessageHandlingContextInterface;
use Gpx\Handlers\BroadcastSessionInvalidated;
use Gpx\Hfx\MessageTransport\Message\ReceivedMessage;
use Prooph\EventSourcing\AggregateRoot;
use Gpx\HfxEventSourcing\HfxAggregateRoot;
class BroadcastSessionInvalidatedTest extends TestCase
{
/** #var HfxRepository */
private $repository;
/** #var Hfx */
private $projectionHelper;
// We have to test handleSynchronousMessage handler whether it is returning sendable response with certain properties in it.
public function testHandleSynchronousMessage()
{
// Expected return value of message() function of $context
$expectedReturnValue = [
"session_id" => "1a92-4376-a8eb-deaf208e1",
"user_id" => "we",
"access_jwt" => "C",
"access_token" => "john#gmail.com",
"refresh_token" => "C",
"refresh_token_expires" => "john#gmail.com"
];
// Expected return value of rawMessage() function of $context
$headerResponseExpected = [
'header' => [
'version' => '2.0',
'originId' => (string)Uuid::uuid4(),
'destination' => 'application/meta#1.0.0',
'sent' => '2017-12-19T10:12:37.941+00:00'
],
'content' => [
'session_id' => "8365526e-fb92-4376-a8eb-deaf208edf61",
'title' => "A task's title."
]
];
// Prophecy means prediction of the future object
// Prediction of $context object starts
$context = $this->prophesize(MessageHandlingContextInterface::class);
$context->message(Argument::any())->willReturn($expectedReturnValue);
$encodedMessage = new JsonEncode($headerResponseExpected);
$rawMessage = ReceivedMessage::fromEncodedMessage($encodedMessage->asString());
$context->rawMessage()->willReturn($rawMessage);
$context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))
->shouldBeCalled();
// Prediction of $context object ends
// Repository Mocking Starts
$ravenAggregateRoot = $this->getMockBuilder(HfxAggregateRoot::class)
->disableOriginalConstructor()
->getMock();
$this->ravenRepository = $this->prophesize(HfxRepository::class);
$this->ravenRepository->get('1a92-4376-a8eb-deaf208e1')->shouldBeCalled()->willReturn($ravenAggregateRoot);
$this->ravenRepository->save(Argument::any())->shouldBeCalled();
// Repository Mocking Ends
// Mocking Hfx and calling the method updateReadModel which will return the string UpdateReadModel
$this->projectionHelper = $this->createMock(Hfx::class);
$this->projectionHelper->method('updateReadModel')
->willReturn('UpdateReadModel');
// Actual calling
$broadcastPlatformSessionInvalidated = new BroadcastSessionInvalidated($this->ravenRepository->reveal(), $this->projectionHelper);
//$broadcastPlatformSessionInvalidated = new BroadcastSessionInvalidated($this->ravenRepository, $this->projectionHelper);
$response = $broadcastPlatformSessionInvalidated->handleSynchronousMessage($context->reveal());
$this->assertInstanceOf('Gpx\Hfx\MessageTransport\Response\SendableResponse', $response);
$this->assertArrayHasKey("responseMessage", $response->content()->data());
$this->assertArrayHasKey("event", $response->content()->data());
$this->assertEquals("Success", $response->content()->data()['responseMessage']);
}
}
When I am executing the test it throws an error
PHPUnit 6.5.4 by Sebastian Bergmann and contributors.
.E 2 / 2 (100%)
Time: 506 ms, Memory: 6.00MB
There was 1 error:
1) Gpx\Tests\Feature\BroadcastSessionInvalidatedTest::testHandleSynchronousMessage
Prophecy\Exception\Call\UnexpectedCallException: Method call:
- sendNonBlockingAsynchronous("session_invalidated", ["session_id" => "1a92-4376-a8eb-deaf208e1", "user_id" => "we", "access_jwt" => "C", "access_token" => "john#gmail.com", "refresh_token" => "C", "refresh_token_expires" => "john#gmail.com"])
on Double\MessageHandlingContextInterface\P3 was not expected, expected calls were:
- message(*)
- rawMessage()
- sendNonBlockingAsynchronous(exact("platform_session_initiated"), type(array))
/vagrant/services/sessions-stream/app/src/Gpx/Handlers/BroadcastSessionInvalidated.php:54
/vagrant/services/sessions-stream/app/tests/Feature/BroadcastPlatformSessionInvalidatedTest.php:107
ERRORS!
Tests: 2, Assertions: 6, Errors: 1.
What I am doing wrong here?
The Exception tells you what's wrong: you use shouldBeCalled() to tell PHPUnit to check that the method sendNonBlockingAsynchronous() gets called with first parameter platform_session_initiated and an array in the second parameter.
// BroadcastSessionInvalidatedTest
$context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))
->shouldBeCalled();
The second condition is met, but in your actual method the first parameter is session_invalidated:
// BroadcastSessionInvalidated
$context->sendNonBlockingAsynchronous('session_invalidated',$content);
So change the expectation to be
// BroadcastSessionInvalidatedTest
$context->sendNonBlockingAsynchronous('session_invalidated', Argument::type("array"))
->shouldBeCalled();
And it will work.

Categories