How to set expectations for inside anonymous functions
KeironLowe opened this issue · 2 comments
Apologies if this is mentioned in the documentation, I've looked but couldn't see anything that would help. Given the following code, how would I go about testing that the code within the anonymous function?
public function register(): void
{
add_action('init', function () {
// Register the post type.
register_post_type($this->postType, $this->arguments);
// Add the columns
if(isset($this->columns)) {
$this->columns->register();
}
});
}
I've tried the following, the assertTrue works fine, but the test fails at expect('register_post_type')->once();
.
expect('register_post_type')->once();
$this->createInstance()->register();
$this->assertTrue(has_action('init', 'function ()'));
Hi,
Brain Monkey does not execute the code that you add to hooks, because to do that it would need to "emulate" WordPress and that's not its scope.
You can imagine Brain Monkey as something that counts how many times add_action
/ do_action
/ add_filter
/ apply_filters
are called and with arguments.
That said, there's the possibility to use whenHappen()
to sort-of hook when one of these functions is called and do "things" with the passed argument. Consider the passed argument to your add_action
is a callback, you could execute it.
For example, assuming a SUT like this:
class Sut {
private $postType;
private $arguments;
private $columns;
public function __construct(string $postType, array $arguments, ?Columns $columns)
{
$this->postType = $postType;
$this->arguments = $arguments;
$this->columns = $columns;
}
public function register(): void
{
add_action('init',
function () {
// Register the post type.
register_post_type($this->postType, $this->arguments);
// Add the columns
if (isset($this->columns)) {
$this->columns->register();
}
});
}
}
You could test in like this:
public function testRegister()
{
$postType = 'post';
$arguments = ['public' => true];
$columns = \Mockery::mock('Columns');
$columns->shouldReceive('register')->once()->withNoArgs();
Brain\Monkey\Functions\expect('register_post_type')
->once()
->with($postType, $arguments);
\Brain\Monkey\Actions\expectAdded('init')
->once()
->with('function ()')
->whenHappen(static function (callable $callback): void {
// This executes the callback passed as argument to add_action('init')
$callback();
});
$instance = new Sut($postType, $arguments, $columns);
$instance->register();
}
Note 1
Documentation for whenHappen
can be found here: https://giuseppe-mazzapica.gitbook.io/brain-monkey/wordpress-specific-tools/wordpress-hooks-done#respond-to-actions
Note 2
While this work, usually tests start to become a lot complex when doing things like that. Probably you can consider to don't add hooks inside register()
but use register()
as hook callback.
That is having a method like thins:
public function register(): void
{
// Register the post type.
register_post_type($this->postType, $this->arguments);
// Add the columns
if (isset($this->columns)) {
$this->columns->register();
}
}
And then in the place where you currently do:
$instance->register();
you could do instead:
add_action('init', [$instance, 'register']);
This way you could test the register
method much more easily, and regarding where the hook is added, you just need to test the hook is actually called with the right callback, and Brain Monkey is perfect for that:
\Brain\Monkey\Actions\expectAdded('init')->once()->with([$instance, 'register']);
Perfect thank you, in my case whenHappen
was what I needed.