May 14, 2023
0
Level 5
Unable to Mock Websocket\Client
I'm trying to write a package that makes use of textalk/websocket with Laravel 10, but I am unable to write mocks for testing it that manage to prevent the library from actually trying to connect.
I am using Pest + the Laravel Pest plugin for tests.
In a normal Laravel 10 install (PHP 8.2), I have set up the following:
// routes/web.php
Route::get('/', [\App\Http\Controllers\Controller::class, 'index']);
// App/Http/Controllers/Controller.php
public function index()
{
$client = App::make(\WebSocket\Client::class, [ 'uri' => 'wss://localhost']);
$client->send('Hello WebSocket.org!');
return view('welcome');
}
// tests/Pest.php
...
uses(
Tests\TestCase::class,
)->in('Unit');
// tests/Unit/ControllerTest.php
use Illuminate\Support\Facades\App;
use Mockery\MockInterface;
test('controller', function () {
$mockBase = Mockery::mock(\WebSocket\Base::class, function (MockInterface $mock) {
$mock->shouldReceive('connect')->once()->with(true);
})->makePartial();
$mockClient = Mockery::mock(\WebSocket\Client::class, function (MockInterface $mock) {
$mock->shouldAllowMockingProtectedMethods();
$mock->shouldReceive('connect')->once()->with(true);
$mock->shouldReceive('send')->once()->with('Hello WebSocket.org!');
})->makePartial();
App::instance(\WebSocket\Base::class, $mockBase);
App::instance(\WebSocket\Client::class, $mockClient);
\Pest\Laravel\call('GET', '/')->assertOk();
});
With the response from running the test:
Expected response status code [200] but received 500.
Failed asserting that 200 is identical to 500.
The following exception occurred during the last request:
WebSocket\ConnectionException: Could not open socket to "localhost:443": Connection refused (61) stream_socket_client(): Unable to connect to ssl://localhost:443 (Connection refused). in ../code/laravel-sandbox/vendor/textalk/websocket/lib/Client.php:128
Stack trace:
#0 ../code/laravel-sandbox/vendor/textalk/websocket/lib/Base.php(79): WebSocket\Client->connect()
#1 ../code/laravel-sandbox/app/Http/Controllers/Controller.php(21): WebSocket\Base->send('Hello WebSocket...')
#2 ../code/laravel-sandbox/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): App\Http\Controllers\Controller->index()
...
From my understanding of Mockery and Laravel, this should work.
$client->send() should be mocked and ultimately is the start of the chain which should prevent the real Websocket client initializing.
Why is the controller unable to load the mocked client from the service container?
Please or to participate in this conversation.