(Using Pest) If the first test doesn't use PHPMockery, but subsequent tests do, they don't work
Pest 3.7.4 Mockery 1.6.12 php-mock-mockery 1.5.0
Given the following test file test.php
<?php
namespace TEST;
use Mockery;
class ABC {
function test() {
$result = json_encode([]);
if($result === false) {
return false;
}
return $result;
}
}
afterEach(function () {
Mockery::close();
});
it('should return the json encoded array', function () {
$abc = new ABC();
$result = $abc->test();
expect($result)->toBe('[]');
});
it('should return false when json_encode fails', function () {
$abc = new ABC();
\phpmock\mockery\PHPMockery::mock(__NAMESPACE__, 'json_encode')
->andReturn(false);
$result = $abc->test();
expect($result)->toBe(false);
});
And running using
php vendor/pestphp/pest/bin/pest test.php
You'll notice that the second test fails with
Failed asserting that '[]' is identical to false.
However when you run
php vendor/pestphp/pest/bin/pest test.php --filter "/should return false when json_encode fails/"
it succeeds
✓ it should return false when json_encode fails
I've done some testing and this happens only when the first test doesn't use PHPMockery::mock().
This setup works
<?php
namespace TEST;
use Mockery;
class ABC {
function test() {
$result = json_encode([]);
if($result === false) {
return false;
}
return $result;
}
}
afterEach(function () {
Mockery::close();
});
it('should return false when json_encode fails', function () {
$abc = new ABC();
\phpmock\mockery\PHPMockery::mock(__NAMESPACE__, 'json_encode')
->andReturn(false);
$result = $abc->test();
expect($result)->toBe(false);
});
it('should return the json encoded array', function () {
$abc = new ABC();
$result = $abc->test();
expect($result)->toBe('[]');
});
and it also doesn't matter if there are other tests after that that use PHPMockery::mock()
<?php
namespace TEST;
use Mockery;
class ABC {
function test() {
$result = json_encode([]);
if($result === false || $result === 'somethingunique') {
return false;
}
return $result;
}
}
afterEach(function () {
Mockery::close();
});
it('should return false when json_encode fails', function () {
$abc = new ABC();
\phpmock\mockery\PHPMockery::mock(__NAMESPACE__, 'json_encode')
->andReturn(false);
$result = $abc->test();
expect($result)->toBe(false);
});
it('should return the json encoded array', function () {
$abc = new ABC();
$result = $abc->test();
expect($result)->toBe('[]');
});
it('should return false when json_encode returns something unique', function () {
$abc = new ABC();
\phpmock\mockery\PHPMockery::mock(__NAMESPACE__, 'json_encode')
->andReturn('somethingunique');
$result = $abc->test();
expect($result)->toBe(false);
});
What could be the problem here?
I care about the order my tests are in so reordering them just for this to work (and adding a comment somewhere about this problem) is not acceptable.
I tried some things and noticed that if i use define before starting the test it works
beforeEach(function () {
\phpmock\mockery\PHPMockery::define(__NAMESPACE__, 'json_encode');
});
Could this be related to Bug #68541?