Unit Testing

Unit Testing

Unit and integration tests are first-class citizens with the PHP SDK. Using the DI container, mocks, stubs, and the provided \Dapr\Mocks\TestClient allows you to have very fine-grained tests.

Testing Actors

With actors, there are two things we’re interested in while the actor is under test:

  1. The returned result based on an initial state
  2. The resulting state based on the initial state
<p>Here&rsquo;s an example test a very simple actor that updates its state and returns a specific value:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TestState.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestState</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\Dapr\Actors\ActorState</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">int</span> $number;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TestActor.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[\Dapr\Actors\Attributes\DaprType(&#39;TestActor&#39;)]
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestActor</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\Dapr\Actors\Actor</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> __construct(<span style="color:#a6e22e">string</span> $id, <span style="color:#66d9ef">private</span> <span style="color:#a6e22e">TestState</span> $state)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">parent</span><span style="color:#f92672">::</span><span style="color:#a6e22e">__construct</span>($id);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">oddIncrement</span>()<span style="color:#f92672">:</span> <span style="color:#a6e22e">bool</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ($this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">number</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">===</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">number</span> <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TheTest.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TheTest</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\PHPUnit\Framework\TestCase</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#a6e22e">\DI\Container</span> $container;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">setUp</span>()<span style="color:#f92672">:</span> <span style="color:#a6e22e">void</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">parent</span><span style="color:#f92672">::</span><span style="color:#a6e22e">setUp</span>();
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// create a default app and extract the DI container from it
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        $app <span style="color:#f92672">=</span> <span style="color:#a6e22e">\Dapr\App</span><span style="color:#f92672">::</span><span style="color:#a6e22e">create</span>(
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">configure</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">fn</span>(<span style="color:#a6e22e">\DI\ContainerBuilder</span> $builder) <span style="color:#f92672">=&gt;</span> $builder<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">addDefinitions</span>(
</span></span><span style="display:flex;"><span>            [<span style="color:#e6db74">&#39;dapr.actors&#39;</span> <span style="color:#f92672">=&gt;</span> [<span style="color:#a6e22e">TestActor</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>]],
</span></span><span style="display:flex;"><span>            [<span style="color:#a6e22e">\Dapr\DaprClient</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span> <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">\DI\autowire</span>(<span style="color:#a6e22e">\Dapr\Mocks\TestClient</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>)]
</span></span><span style="display:flex;"><span>        ));
</span></span><span style="display:flex;"><span>        $app<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">run</span>(<span style="color:#a6e22e">fn</span>(<span style="color:#a6e22e">\DI\Container</span> $container) <span style="color:#f92672">=&gt;</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span> <span style="color:#f92672">=</span> $container);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">testIncrementsWhenOdd</span>()
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        $id      <span style="color:#f92672">=</span> <span style="color:#a6e22e">uniqid</span>();
</span></span><span style="display:flex;"><span>        $runtime <span style="color:#f92672">=</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">get</span>(<span style="color:#a6e22e">\Dapr\Actors\ActorRuntime</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>);
</span></span><span style="display:flex;"><span>        $client  <span style="color:#f92672">=</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getClient</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// return the current state from http://localhost:1313/reference/api/actors_api/
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        $client<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">register_get</span>(<span style="color:#e6db74">&#34;/actors/TestActor/</span><span style="color:#e6db74">$id</span><span style="color:#e6db74">/state/number&#34;</span>, <span style="color:#a6e22e">code</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">200</span>, <span style="color:#a6e22e">data</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// ensure it increments from http://localhost:1313/reference/api/actors_api/
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        $client<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">register_post</span>(
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;/actors/TestActor/</span><span style="color:#e6db74">$id</span><span style="color:#e6db74">/state&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">code</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">204</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">response_data</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">expected_request</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>                [
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#39;operation&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;upsert&#39;</span>,
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#39;request&#39;</span>   <span style="color:#f92672">=&gt;</span> [
</span></span><span style="display:flex;"><span>                        <span style="color:#e6db74">&#39;key&#39;</span>   <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;number&#39;</span>,
</span></span><span style="display:flex;"><span>                        <span style="color:#e6db74">&#39;value&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">4</span>,
</span></span><span style="display:flex;"><span>                    ],
</span></span><span style="display:flex;"><span>                ],
</span></span><span style="display:flex;"><span>            ]
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        $result <span style="color:#f92672">=</span> $runtime<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">resolve_actor</span>(
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#39;TestActor&#39;</span>,
</span></span><span style="display:flex;"><span>            $id,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">fn</span>($actor) <span style="color:#f92672">=&gt;</span> $runtime<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">do_method</span>($actor, <span style="color:#e6db74">&#39;oddIncrement&#39;</span>, <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">assertTrue</span>($result);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">getClient</span>()<span style="color:#f92672">:</span> <span style="color:#a6e22e">\Dapr\Mocks\TestClient</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">get</span>(<span style="color:#a6e22e">\Dapr\DaprClient</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TestState.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestState</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\Dapr\Actors\ActorState</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">int</span> $number;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TestActor.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[\Dapr\Actors\Attributes\DaprType(&#39;TestActor&#39;)]
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TestActor</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\Dapr\Actors\Actor</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> __construct(<span style="color:#a6e22e">string</span> $id, <span style="color:#66d9ef">private</span> <span style="color:#a6e22e">TestState</span> $state)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">parent</span><span style="color:#f92672">::</span><span style="color:#a6e22e">__construct</span>($id);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">oddIncrement</span>()<span style="color:#f92672">:</span> <span style="color:#a6e22e">bool</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> ($this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">number</span> <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">===</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">number</span> <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TheTest.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TheTest</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\PHPUnit\Framework\TestCase</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">testNotIncrementsWhenEven</span>() {
</span></span><span style="display:flex;"><span>        $container <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">\DI\Container</span>();
</span></span><span style="display:flex;"><span>        $state <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">TestState</span>($container, $container);
</span></span><span style="display:flex;"><span>        $state<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">number</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>;
</span></span><span style="display:flex;"><span>        $id <span style="color:#f92672">=</span> <span style="color:#a6e22e">uniqid</span>();
</span></span><span style="display:flex;"><span>        $actor <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">TestActor</span>($id, $state);
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">assertFalse</span>($actor<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">oddIncrement</span>());
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">assertSame</span>(<span style="color:#ae81ff">4</span>, $state<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">number</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>

Testing Transactions

When building on transactions, you’ll likely want to test how a failed transaction is handled. In order to do that, you need to inject failures and ensure the transaction matches what you expect.

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// MyState.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#[\Dapr\State\Attributes\StateStore(&#39;statestore&#39;, \Dapr\consistency\EventualFirstWrite::class)]
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyState</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\Dapr\State\TransactionalState</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">string</span> $value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// SomeService.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SomeService</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> __construct(<span style="color:#66d9ef">private</span> <span style="color:#a6e22e">MyState</span> $state) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">doWork</span>() {
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">begin</span>();
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello world&#34;</span>;
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">commit</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TheTest.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TheTest</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\PHPUnit\Framework\TestCase</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#a6e22e">\DI\Container</span> $container;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">setUp</span>()<span style="color:#f92672">:</span> <span style="color:#a6e22e">void</span>
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">parent</span><span style="color:#f92672">::</span><span style="color:#a6e22e">setUp</span>();
</span></span><span style="display:flex;"><span>        $app <span style="color:#f92672">=</span> <span style="color:#a6e22e">\Dapr\App</span><span style="color:#f92672">::</span><span style="color:#a6e22e">create</span>(<span style="color:#a6e22e">configure</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">fn</span>(<span style="color:#a6e22e">\DI\ContainerBuilder</span> $builder)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">=&gt;</span> $builder<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">addDefinitions</span>([<span style="color:#a6e22e">\Dapr\DaprClient</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span> <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">\DI\autowire</span>(<span style="color:#a6e22e">\Dapr\Mocks\TestClient</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>)]));
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span> <span style="color:#f92672">=</span> $app<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">run</span>(<span style="color:#a6e22e">fn</span>(<span style="color:#a6e22e">\DI\Container</span> $container) <span style="color:#f92672">=&gt;</span> $container);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">getClient</span>()<span style="color:#f92672">:</span> <span style="color:#a6e22e">\Dapr\Mocks\TestClient</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">get</span>(<span style="color:#a6e22e">\Dapr\DaprClient</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">testTransactionFailure</span>() {
</span></span><span style="display:flex;"><span>        $client <span style="color:#f92672">=</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getClient</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// create a response from https://docs.dapr.io/reference/api/state_api/
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        $client<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">register_post</span>(<span style="color:#e6db74">&#39;/state/statestore/bulk&#39;</span>, <span style="color:#a6e22e">code</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">200</span>, <span style="color:#a6e22e">response_data</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#39;key&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;value&#39;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">// no previous value
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>            ],
</span></span><span style="display:flex;"><span>        ], <span style="color:#a6e22e">expected_request</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#39;keys&#39;</span> <span style="color:#f92672">=&gt;</span> [<span style="color:#e6db74">&#39;value&#39;</span>],
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#39;parallelism&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">10</span>
</span></span><span style="display:flex;"><span>        ]);
</span></span><span style="display:flex;"><span>        $client<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">register_post</span>(<span style="color:#e6db74">&#39;/state/statestore/transaction&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">code</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">200</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">response_data</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">null</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">expected_request</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#39;operations&#39;</span> <span style="color:#f92672">=&gt;</span> [
</span></span><span style="display:flex;"><span>                    [
</span></span><span style="display:flex;"><span>                        <span style="color:#e6db74">&#39;operation&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;upsert&#39;</span>,
</span></span><span style="display:flex;"><span>                        <span style="color:#e6db74">&#39;request&#39;</span> <span style="color:#f92672">=&gt;</span> [
</span></span><span style="display:flex;"><span>                            <span style="color:#e6db74">&#39;key&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;value&#39;</span>,
</span></span><span style="display:flex;"><span>                            <span style="color:#e6db74">&#39;value&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;hello world&#39;</span>
</span></span><span style="display:flex;"><span>                        ]
</span></span><span style="display:flex;"><span>                    ]
</span></span><span style="display:flex;"><span>                ]
</span></span><span style="display:flex;"><span>            ]
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>        $state <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">MyState</span>($this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span>, $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">container</span>);
</span></span><span style="display:flex;"><span>        $service <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">SomeService</span>($state);
</span></span><span style="display:flex;"><span>        $service<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">doWork</span>();
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">assertSame</span>(<span style="color:#e6db74">&#39;hello world&#39;</span>, $state<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">value</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// MyState.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#[\Dapr\State\Attributes\StateStore(&#39;statestore&#39;, \Dapr\consistency\EventualFirstWrite::class)]
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyState</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\Dapr\State\TransactionalState</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">string</span> $value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// SomeService.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SomeService</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> __construct(<span style="color:#66d9ef">private</span> <span style="color:#a6e22e">MyState</span> $state) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">doWork</span>() {
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">begin</span>();
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello world&#34;</span>;
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">state</span><span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">commit</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// TheTest.php
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TheTest</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">\PHPUnit\Framework\TestCase</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">testTransactionFailure</span>() {
</span></span><span style="display:flex;"><span>        $state <span style="color:#f92672">=</span> $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">createStub</span>(<span style="color:#a6e22e">MyState</span><span style="color:#f92672">::</span><span style="color:#a6e22e">class</span>);
</span></span><span style="display:flex;"><span>        $service <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">SomeService</span>($state);
</span></span><span style="display:flex;"><span>        $service<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">doWork</span>();
</span></span><span style="display:flex;"><span>        $this<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">assertSame</span>(<span style="color:#e6db74">&#39;hello world&#39;</span>, $state<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">value</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>