PHP 单元故障测试
PHP unit failure testing
我必须测试此 class 的失败条件
<?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.'
]);
}
}
}
以下是我写的测试用例
<?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']);
}
}
这是我遇到的 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.
任何人都可以澄清我在这里做错了什么吗?
你的 setUp()
方法在 每个 测试之前被调用,所以 testHandleSynchronousMessageForFailure()
也期待 sendNonBlockingAsynchronous()
被调用:
$this->context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))
->shouldBeCalled();
即使你在失败测试中调用shouldNotBeCalled()
。因此,将 shouldBeCalled()
调用移动到 testHandleSynchronousMessageForSuccess()
,这样它会期望在成功测试中调用它,而 not 在失败时调用测试。
您还应该告诉 PHPUnit 在失败测试中期望 IdNotDefinedException
:
$this->expectException(Gpx\Exceptions\IdNotDefinedException::class);
我必须测试此 class 的失败条件
<?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.'
]);
}
}
}
以下是我写的测试用例
<?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']);
}
}
这是我遇到的 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.
任何人都可以澄清我在这里做错了什么吗?
你的 setUp()
方法在 每个 测试之前被调用,所以 testHandleSynchronousMessageForFailure()
也期待 sendNonBlockingAsynchronous()
被调用:
$this->context->sendNonBlockingAsynchronous('platform_session_initiated', Argument::type("array"))
->shouldBeCalled();
即使你在失败测试中调用shouldNotBeCalled()
。因此,将 shouldBeCalled()
调用移动到 testHandleSynchronousMessageForSuccess()
,这样它会期望在成功测试中调用它,而 not 在失败时调用测试。
您还应该告诉 PHPUnit 在失败测试中期望 IdNotDefinedException
:
$this->expectException(Gpx\Exceptions\IdNotDefinedException::class);