Testing Events
Most modules/plugins support events that are triggered that enable modules/plugins to place event listeners which modify actions and behaviours. This increases the flexibility and usability of modules/plugins.
Seeing as events and the triggering thereof are routed through some complex Yii2 (opens new window) based functionality some specific steps must be taken to test code that triggers events.
# Testing Event Code
Craft provides a simple helper method that allows you to test event codes.
Firstly you need to ensure that your test class has a $tester
property.
Once this class property is declared you can call the following method:
$this->tester->expectEvent(MyComponent::class, MyComponent::AN_EVENT, function() {
MyModule::getInstance()->myComponent->myMethod();
});
The first argument is the class from which your event gets triggered. Similarly to the first argument you pass when calling
$this->trigger()
from a class that extendscraft\base\Component
.The second argument is the name of your event. Similarly to the second argument you pass when calling
$this->trigger()
from a class that extendscraft\base\Component
.The third argument is is a closure that must contain the code to trigger an event. If the callback does not trigger the event the test will fail.
This is a watered down example of the expectEvent
method. There are two optional
parameters that give you a whole lot of extra power - see below.
# Additional Properties
If you want more fine-grained control over your event testing code the expectEvent
method
has two optional parameters.
# string $eventInstance = ''
The this is the fourth property of expectEvent
. If you want to check the class of the
event that was passed you can set this property. The property will be
compared using instanceof (opens new window).
# array $eventValues = []
The eventValues
property accepts an array that can be specially setup to
validate the properties of the event that was passed.
# Setting up $eventValues
Craft provides a special helper method that is recommended
to configure $eventValues
. You can call $this->tester->createEventItems()
and pass in an array with the following keys:
# eventPropName
The name of the event property you want to test.
I.E. if you want to check the name of yii\base\Event
you would set this to
'name'
.
# type
You can choose from the following:
use craft\test\EventItem;
EventItem::TYPE_CLASS
or
use craft\test\EventItem;
EventItem::TYPE_OTHERVALUE
Where
TYPE_CLASS
instructs Craft that when we access the$eventPropName
on the passed event an object will be returned.TYPE_OTHERVALUE
instructs Craft to accept any non-object value.
# desiredClass
If you have set TYPE_CLASS
you can pass in an additional desiredClass
property.
Craft will then compare the returned object to the desiredClass
property using instanceof
.
# desiredValue
desiredValue
is designed to check the property values of the event that is passed.
This can depend based on the type
argument:
# When Type is EventItem::TYPE_OTHERVALUE
Here you can set the desiredValue
to anything you want. The result of
accessing the event using the eventPropName property will be directly compared
using assertSame()
.
# When Type is EventItem::TYPE_CLASS
Craft allows you to check the individual properties of the returned object. In order to do this you must enter a key-value array where:
key
Is the name of a property belonging to the object that was returned when accessing the event using eventPropName.value
The value that the above property above should be set to.
See a complete example below:
use yii\base\Event;
use craft\test\EventItem;
$this->tester->expectEvent(SomeComponent::class, SomeComponent::SOME_EVENT, function() {
// Code that should trigger an event goes here.
}, Event::class,
$this->tester->createEventItems([
[
// The $event->sender prop is a \stdClass where the $key property is set to 'value'
'eventPropName' => 'sender',
'type' => EventItem::TYPE_CLASS,
'desiredClass' => \stdClass::class,
'desiredValue' => [
'key' => 'value'
],
],
[
// The $event->name prop string set to 'someEvent'.
'eventPropName' => 'name',
'type' => EventItem::TYPE_OTHERVALUE,
'desiredValue' => 'someEvent'
]
]
));