Mockery,App Instance没有进行某些laravel测试

时间:2018-03-06 13:14:02

标签: php laravel testing phpunit mockery

基本上,我的问题是;为什么$this->app->instance()调用在模拟对象的一个​​实例上工作,而另一个不在...

在下面的示例中, getGroupSingleSignOnLink 函数实际上被调用,另一个被模拟并且测试通过...

TEST

namespace Tests\Feature;

use App\Models\Group;
use App\Models\User;
use Tests\TestCase;
use App\Clients\SingleSignOnApi;
use Mockery;

class SingleSignOnTest extends TestCase
{

    private $validUrl = 'http://www.google.com';

    public function setUp()
    {
        parent::setUp();

        $single_sign_on = Mockery::mock(SingleSignOnApi::class);

        $single_sign_on->shouldReceive('getGroupSingleSignOnLink')->andReturn($this->validUrl);
        $single_sign_on->shouldReceive('getSingleSignOnLink')->andReturn($this->validUrl);

        $this->app->instance(SingleSignOnApi::class, $single_sign_on);
    }

    //THIS TEST FAILS, SingleSignOnApi Class Not Mocked
    public function testGroupAuthConnection()
    {
        $group = Group::whereNotNull('external_platform_key')->first();
        $user = $group->users()->first();

        $this->be($user);

        $group_sso = $group->groupAuthConnections()->first();
        $response = $this->get(route('sso.group.connect', ['id' => $group_sso->id]));

        $response->assertRedirect($this->validUrl);
        $response->assertSessionMissing('__danger');
    }

    //THIS TEST PASSES, The SingleSignOnApi Class is Mocked
    public function testAuthConnectionConnect()
    {
        $user = User::first();
        $this->be($user);

        $sso = $user->authConnections()->firstOrFail();
        $response = $this->get(route('sso.connect', ['id' => $sso->id]));

        $response->assertRedirect($this->validUrl);
        $response->assertSessionMissing('__danger');
    }

}

控制器功能 - 测试模块工作

public function connect($id)
{
    $auth_connection = $this->findAuthConnection($id, Auth::user());

    $sso_client = App::make(SingleSignOnApi::class);
    $url        = $sso_client->getSingleSignOnLink($auth_connection);

    return redirect($url);
}

控制器功能 - 测试模块不工作

public function connect($id)
{
    $group_ids = Auth::user()->groups()->pluck('groups.id')->toArray();

    $group_auth_connection = $this->findGroupAuthConnection($id, Auth::user());

    //This is the Mocked Object in my Test: SingleSignOnApi
    $sso_client = App::make(SingleSignOnApi::class, [$group_auth_connection->group->external_platform_key]);
    $url = $sso_client->getGroupSingleSignOnLink($group_auth_connection, Auth::user());

    return redirect($url);
}

1 个答案:

答案 0 :(得分:1)

我将使用Quickbooks作为一个例子来说明我是如何让我一直为我工作的。

这是我的AppServiceProvider,定义了我创建的自定义QuickbooksSDK类:

...
    public function boot()
    {
        $this->app->bind(QuickbooksSDK::class, function($app) {
            return new QuickbooksSDK(
                new GuzzleHttp\Client([
                    'base_uri' => config('invoicing.baseUri'),
                    'timeout' => 3,
                    'headers' => [
                        'Authorization' => 'Bearer '.config('invoicing.apiKey'),
                        'Accept' => 'application/json'
                    ],
                    'http_errors' => false
                ]),
                config('invoicing.apiKey'),
                env('QUICKBOOKS_REFRESH_TOKEN'),
                env('QUICKBOOKS_CLIENT_ID'),
                env('QUICKBOOKS_CLIENT_SECRET')
            );
        });
    }

然后我创建了第二个自定义类,称为QuickbooksInvoicingDriver,它从服务容器中获取实例化的SDK类:

public function __construct()
{
    $this->api = app(QuickbooksSDK::class);
}

最后,在我的测试课中,我可以使用自己的自定义响应来模拟QuickbooksSDK,以便更轻松地进行测试:

    $vendorResponse = '{"Vendor": {"Balance": 0,"Vendor1099": false,"CurrencyRef": {"value": "GYD","name": "Guyana Dollar"},"domain": "QBO","sparse": false,"Id": "25","SyncToken": "0","MetaData": {"CreateTime": "2018-04-04T12:36:47-07:00","LastUpdatedTime": "2018-04-04T12:36:47-07:00"},"DisplayName": "daraul","PrintOnCheckName": "daraul","Active": true},"time": "2018-04-04T12:36:47.576-07:00"}';

    $mock = new MockHandler([
        new Response(200, [], $vendorResponse),
    ]);

    $handler = HandlerStack::create($mock);
    $client = new Client(['handler' => $handler]);
    $api = new QuickbooksSDK(
        $client,
        'test',
        'test',
        'test',
        'test'
    );

    $this->app->instance(QuickbooksSDK::class, $api);

现在我可以正常运行我的测试,而不用担心第三方。这些链接对我很有帮助:

http://docs.guzzlephp.org/en/stable/testing.html

https://laravel.com/docs/5.5/container

如果这有用,请告诉我。