codeception / mockerymodule Goto Github PK
View Code? Open in Web Editor NEWMockery module for Codeception
License: MIT License
Mockery module for Codeception
License: MIT License
When mockery expectations fail, the currently running suite terminates because of exception thrown. I think the good solution would be to catch Mockery\Exception\*
and fail the current test only.
Tell me how to fail the current test from the place where Mockery::close()
is called and I'll prepare a pull request. \Codeception\Module::fail()
terminates the suite completely?
Unable to mock any methods that have a boolean return type. Need to do more research to see if it's breaking on other primitives.
Example:
public function toBeTested() : bool
{
return true;
}
The mocked version does not include the bool
return type and breaks.
@DavertMik I've released a new version, however it is not visible on Packagist. Can you click the force-update button or preferably add me as maintainer?
I'd like to use the recently released stable Mockery 0.9 but this package doesn't allow me to do that because of this in composer.json.
"require": {
"mockery/mockery": "dev-master@dev"
},
Is there a reason for it? Just @dev
would be enough in my opinion.
@DavertMik Can you please tag new stable version as discussed in #3 or grant me push privileges so that I can do it myself?
According to the Mockery docs, I can mock hard dependencies by doing e.g.:
$mock = m::mock('overload:SomeNamespace\SomeClass');
However, this only works if the mocked class is not loaded somewhere else in the test suite.
Quoting from the docs:
To make this possible, we’ll tell PHPUnit to run the tests that have overloaded classes in separate processes and to not preserve global state. That way we’ll avoid having the overloaded class included more than once. Of course this has its downsides as these tests will run slower.
This means adding the @runTestsInSeparateProcesses
and @preserveGlobalState disabled
annotations. When I did so, I got this error:
PHPUnit_Framework_Exception: PHP Fatal error: Class 'Codeception\TestCase\Test' not found in [snip]
Fatal error: Class 'Codeception\TestCase\Test' not found in [snip]
After some searching, I found this GitHub issue, which says that Codeception doesn't support the @runTestsInSeparateProcesses
annotation.
Is there any way around this, or some other way to mock hard dependencies?
Currently using this module requires changes in each test.
I have found an ugly way to alleviate that problem.
The code below was tested for Cest
type tests only. It should not break for any other test type but might simply not work.
use Codeception\Lib\Di;
use Codeception\Module;
use Codeception\TestInterface;
class Mockery extends Module
{
public function _before(TestInterface $test)
{
$meta = $test->getMetadata();
$rc = new \ReflectionClass($meta);
$prop = $rc->getProperty('services');
$prop->setAccessible(true);
$services = $prop->getValue($meta);
/** @var Di $di */
$di = $services['di'];
$services['di'] = new class($di, $test) extends Di {
public function __construct(Di $fallback, private readonly TestInterface $test)
{
parent::__construct($fallback);
}
public function injectDependencies(object $object, string $injectMethodName = self::DEFAULT_INJECT_METHOD_NAME, array $defaults = []): void
{
if ($object === $this->test) {
parent::injectDependencies(...func_get_args());
return;
}
// We check if the object is our test, if so we close mockery after.
codecept_debug(['CALLING',
get_class($object),
$injectMethodName
]);
try {
parent::injectDependencies(...func_get_args());
\Mockery::close();
} catch (\Throwable $t) {
\Mockery::resetContainer();
throw $t;
}
\Mockery::close();
}
};
$prop->setValue($meta, $services);
}
}
Essentially we hijack the Di
container and replace it with a custom implementation. Based on the fact that for Cest
files the actual test is ran like this:
$this->getMetadata()->getService('di')->injectDependencies($this->testInstance, $methodName, $context);
We abuse this to insert a mockery closure after calling the test method.
While I'm happy to make a PR for this, I'm not sure it should be in an "official" repository. I probably don't have time to implement a proper fix where we add an event to allow modules to fail a test before it is finished.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.