专栏首页IT码农写Laravel测试代码(3)

写Laravel测试代码(3)

本文主要聊一聊写测试时如何mock第三方json api数据。

在开发时经常会调用第三方API接口,抓取json api data后进行加工处理,那如何写测试呢?如何mock数据呢?

这里举一个简单例子,AccountController::class调用Connector::class, Connector::class 会调用第三方 json api来读取数据,代码如下:

<?php

declare(strict_types=1);

namespace App\Http\Controllers;

class AccountController extends Controller
{
    /**
     * @var Connector
     */
    private $connector;

    public function index()
    {
        $connector = $this->getConnector();

        return $connector->call('accounts');
    }

    public function show(string $id)
    {
        $connector = $this->getConnector();

        return $connector->call('accounts/' . $id);
    }

    private function getConnector()
    {
        if (!$this->connector) {
            $this->connector = new Connector();
        }

        return $this->connector;
    }
}



namespace App\Http\Controllers;

use GuzzleHttp\Client;
use Illuminate\Http\Request;

class Connector
{
    public function call(string $path): array
    {
        $client = new Client();

        $response = $client->request(Request::METHOD_GET, config('app.url') . DIRECTORY_SEPARATOR . $path);

        return \GuzzleHttp\json_decode($response);
    }
}

代码很简单,但是场景却经常会遇到,关键是如何mock数据而不是发送真实http请求数据。其实很简单,只需运用Mockery库mock请求代码,从本地读取fixtures数据

首先是在tests/fixtures文件夹下准备下fixtures数据,这些json文件的数据都是真实的接口返回的数据,可以先用postman或其他工具拿到真实数据, simple_dataset 是dataset的名称,可以自定义,一般项目里都会有一个或多个dataset数据集,vendor 是第三方名称,自定义:

然后写上AccountControllerTest::class

<?php

declare(strict_types=1);

namespace Tests\Feature;

use Illuminate\Http\Request;

class AccountControllerTest extends TestCase
{
    public function testIndex()
    {
        $response = $this->call(Request::METHOD_GET, 'api/v1/accounts');

        dump($response->json());
    }

    public function testShow()
    {
        $response = $this->call(Request::METHOD_GET, 'api/v1/accounts/1');

        dump($response->json());
    }
}

然后写上路由:

Route::group(['prefix' => 'v1'], function () {
    $resources = [
        'accounts' => [\App\Http\Controllers\AccountController::class => ['index', 'show']],
    ];

    foreach ($resources as $name => $controllers) {
        foreach ($controllers as $fqcn => $actions) {
            Route::resource($name, $fqcn, ['only' => $actions]);
        }
    }
});

既然用了全局类名\App\Http\Controllers\AccountController::class,那就别忘了在app/Providers/RouteServiceProvider::mapApiRoutes 抹掉namespace

    protected function mapApiRoutes()
    {
        Route::prefix('api')
             ->middleware('api')
             ->group(base_path('routes/api.php'));
    }

最后同时在TestCase::class写上mock数据代码

<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Http\Controllers\Connector;
use Symfony\Component\Finder\SplFileInfo;
use Tests\TestCase as BaseTestCase;

class TestCase extends BaseTestCase
{
    protected const MOCK_PATH = 'tests/fixtures/simple_dataset/vendor'; // tests/fixtures/{$dataset_name}/{$vendor_name}

    public function setUp()
    {
        parent::setUp();
    
        /** @see http://docs.mockery.io/en/latest/cookbook/mocking_hard_dependencies.html?highlight=overload */
        $mock      = \Mockery::mock('overload:' . Connector::class); // Mock hard dependencies
        $mock_path = base_path(static::MOCK_PATH);

        /** @var SplFileInfo[] $files */
        $files = \File::allFiles($mock_path);

        foreach ($files as $file) {
            $api_name = substr($file->getRelativePathname(), 0, -5); // remove '.json'

            // mock Connector::call('accounts/1') && Connector::call('accounts')
            $mock->shouldReceive('call')->with($api_name)->andReturn(\GuzzleHttp\json_decode(file_get_contents($file->getRealPath()), true));
        }
    }
}

这样执行测试时就实现了读取本地的真实json数据,而不用发起真实的http请求。两个测试的response数据的确来源于本地json文件的数据:

其实,就是一句话,写测试时如果调用了第三方 json api 读取数据时,使用Mockery库去mock数据,数据来源于本地文件夹的数据,且是真实有效的数据。至于mock部分的代码想咋写就咋写。同时,上面代码里还需要注意一点是,由于Connector::class是AccountController::class 的 hard dependency,别忘了加上 overload, 代码里已经添加链接,可看官网介绍

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • git相关操作

    Text-to-speech function is limited to 200 characters

    botkenni
  • git部署线上项目

    2.还有就是目录的所有者何所有组的问题chowm -R git:git 目录

    botkenni
  • yii2底层源码分析 [ 2.0 版本 ]

    我是从入口处分析的。 $mysiteRoot/frontend 首先:$mysiteRoot/frontend/index.php

    botkenni
  • 【网络安全】2月微软安全更新修复56个安全漏洞,建议立刻更新!

    大家好,我是网络安全专家超级科技,这里为大家提供最新网络安全资讯!2月9日,微软发布2月安全更新,共修复了56个安全漏洞,其中1个0 day在野漏洞和55个其他...

    超级科技
  • Spring之RestTemplate使用小结一

    作为一个Java后端,需要通过HTTP请求其他的网络资源可以说是一个比较常见的case了;一般怎么做呢?

    一灰灰blog
  • 180813-Spring之RestTemplate使用小结一

    作为一个Java后端,需要通过HTTP请求其他的网络资源可以说是一个比较常见的case了;一般怎么做呢?

    一灰灰blog
  • 漏洞情报|2021年1月“微软补丁日” 多个产品高危漏洞风险通告

    近日,腾讯云安全运营中心监测到,微软发布了2021年2月的例行安全更新公告,涉及漏洞数87个,其中严重级别漏洞11个,重要级别44个。远程代码执行漏洞 21个...

    云鼎实验室
  • Jsoup+Htmlunit抓取图片遇到坑

    Jsoup是用于解析HTML,就类似XML解析器用于解析XML。 Jsoup它解析HTML成为真实世界的HTML。

    赵哥窟
  • 是兄弟,就一起吃鸡!来,这个小程序拉你「进群」

    最近,一款「佛系养蛙」的日本游戏风靡网络,相信你已经在朋友圈见过它了。不出意外,这个「旅行青蛙」也迅速登上了中国区 AppStore 的免费游戏的榜首。

    知晓君
  • 2 下载GATK需要的参考基因组文件

    直接去gatk官网下载,下载链接为ftp://ftp.broadinstitute.org/bundle/

    Y大宽

扫码关注云+社区

领取腾讯云代金券