prooph/service-bus

QueryBus testing

Closed this issue · 9 comments

Hi!

I am currently finding my way around with QueryBus. And I got confused with testing it. I created an empty project, pulled up just a few things:

"require": {
        "prooph/service-bus": "^6.0",
        "react/promise": "^2.5"
    },
    "require-dev": {
        "phpunit/phpunit": "^6.1"
    }

and then run this test:

<?php
declare(strict_types=1);


use PHPUnit\Framework\TestCase;
use Prooph\ServiceBus\QueryBus;

final class QueryTest extends TestCase
{
    function test_query() {
    
        $queryBus = new QueryBus();
        $queryBus->dispatch('anyname')->then(function(){
            //will not get there anyway
        }, function(Throwable $e){
            // Does nothing
            $this->fail($e->getMessage());
        });
        
    
    }
}

And it is green.
I get control in second callable, but PHPUnit did not respect the fail() call at all.

Do you have any suggestions on how to test queries / how to fix that test?

P.s. I browsed through the proophessor-do but did not find query tests there.

basz commented

This happens because you tell phpunit to expect an exception thrown, but what actually happens is that the promise returns an Exception instance, not a 'thrown' one...

however, since you would normally get the result of either method and do something with it I recommend this which works also;

    public function test_query()
    {
        $succesCalled = false;
        $failedCalled = false;

        $queryBus = new QueryBus();
        $queryBus->dispatch('anyname')->then(
            function () use (&$succesCalled) {
                $succesCalled = true;
            },
            function (Throwable $e) use (&$failedCalled) {
                $failedCalled = true;
            });

        $this->assertFalse($succesCalled);
        $this->assertTrue($failedCalled);
    }

or

    public function test_query()
    {
        $queryBus = new QueryBus();
        $queryBus->dispatch('anyname')->then(
            function ($response) use (&$result) {
                $result = $response;
            },
            function ($response) use (&$result) {
                $result = $response;
            });

        $this->assertInstanceOf(\Prooph\ServiceBus\Exception\RuntimeException::class, $result);
        $this->assertContains('Message dispatch failed. See previous exception for details.', $result->getMessage());
    }

Thanks for the code samples! Your suggestions are clear.

I understand that this is more the issue from reactphp/promise package than from the Prooph.
I think it is worth mentioning this conversation on reactphp/promise page which led me to this done() function.

I managed to find another way to properly fail the test (by calling fail()) by adding done() call at the end:

<?php
declare(strict_types=1);

use PHPUnit\Framework\TestCase;
use Prooph\ServiceBus\QueryBus;

final class QueryTest extends TestCase
{
    function test_query()
    {
        
        $queryBus = new QueryBus();
        $queryBus->dispatch('anyname')
                 ->then(function () {
                     //....
                 }, function (Throwable $e) {
                     $this->fail($e->getMessage());
                 })
                 ->done(); //    <--- THIS IS THE KEY HERE
        
    }
}

Can this issue be closed now?

basz commented

should we add that done() thing?

maybe add some documentation? PR's are welcome :)

oqq commented

We should refer to the promise package instead of document how promises works by our own.
I use always that simple rule:
Either return the promise or call done() on it.

Guys, can you take a look at this issue as well, as it is relatively the same to this issue.
prooph/laravel-package#24

Documentations says nothing about how to resolve Deferred object inside finder when FinalizeGuard plugin is enabled.

I managed to reproduce the error in a simple test:
https://github.com/lezhnev74/prooph-query-test/blob/prooph-bare/tests/QueryTest.php

Results:

  • executing query with no guards - pass
  • executing query with RouteGuard - pass
  • executing query with FinalizeGuard - fail

Looks like I follow exactly what @basz suggested

basz commented

Open a new issue. Definitly a problem i would think