Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
.. index::
2
    single: Cookbook; Complex Argument Matching With Mockery::on
3
 
4
Complex Argument Matching With Mockery::on
5
==========================================
6
 
7
When we need to do a more complex argument matching for an expected method call,
8
the ``\Mockery::on()`` matcher comes in really handy. It accepts a closure as an
9
argument and that closure in turn receives the argument passed in to the method,
10
when called. If the closure returns ``true``, Mockery will consider that the
11
argument has passed the expectation. If the closure returns ``false``, or a
12
"falsey" value, the expectation will not pass.
13
 
14
The ``\Mockery::on()`` matcher can be used in various scenarios — validating
15
an array argument based on multiple keys and values, complex string matching...
16
 
17
Say, for example, we have the following code. It doesn't do much; publishes a
18
post by setting the ``published`` flag in the database to ``1`` and sets the
19
``published_at`` to the current date and time:
20
 
21
.. code-block:: php
22
 
23
    <?php
24
    namespace Service;
25
    class Post
26
    {
27
        public function __construct($model)
28
        {
29
            $this->model = $model;
30
        }
31
 
32
        public function publishPost($id)
33
        {
34
            $saveData = [
35
                'post_id' => $id,
36
                'published' => 1,
37
                'published_at' => gmdate('Y-m-d H:i:s'),
38
            ];
39
            $this->model->save($saveData);
40
        }
41
    }
42
 
43
In a test we would mock the model and set some expectations on the call of the
44
``save()`` method:
45
 
46
.. code-block:: php
47
 
48
    <?php
49
    $postId = 42;
50
 
51
    $modelMock = \Mockery::mock('Model');
52
    $modelMock->shouldReceive('save')
53
        ->once()
54
        ->with(\Mockery::on(function ($argument) use ($postId) {
55
            $postIdIsSet = isset($argument['post_id']) && $argument['post_id'] === $postId;
56
            $publishedFlagIsSet = isset($argument['published']) && $argument['published'] === 1;
57
            $publishedAtIsSet = isset($argument['published_at']);
58
 
59
            return $postIdIsSet && $publishedFlagIsSet && $publishedAtIsSet;
60
        }));
61
 
62
    $service = new \Service\Post($modelMock);
63
    $service->publishPost($postId);
64
 
65
    \Mockery::close();
66
 
67
The important part of the example is inside the closure we pass to the
68
``\Mockery::on()`` matcher. The ``$argument`` is actually the ``$saveData`` argument
69
the ``save()`` method gets when it is called. We check for a couple of things in
70
this argument:
71
 
72
* the post ID is set, and is same as the post ID we passed in to the
73
  ``publishPost()`` method,
74
* the ``published`` flag is set, and is ``1``, and
75
* the ``published_at`` key is present.
76
 
77
If any of these requirements is not satisfied, the closure will return ``false``,
78
the method call expectation will not be met, and Mockery will throw a
79
``NoMatchingExpectationException``.
80
 
81
.. note::
82
 
83
    This cookbook entry is an adaption of the blog post titled
84
    `"Complex argument matching in Mockery" <https://robertbasic.com/blog/complex-argument-matching-in-mockery/>`_,
85
    published by Robert Basic on his blog.