thinkphp6 phpunit单元测试完整用法

概述

  • 折腾了一个上午搞这个单元测试,的亏是通了,不然要面壁去了。

thinkphp6官方并没有支持phpunit的集成使用,不知道为什么,虽然不妨碍我们直接使用phpuint,单局限性很大,我们只能对通用类和不涉及框架层面进行测试,如接口验证之类。这样的单元测试意义并不大,不能注入到核心里面,还不如直接看接口返回得了,造啥测试,既然用了必然是想要代码质量更高的。

打通任督二脉

想要运行并测试框架内部的逻辑,那么怎么引入就成了最大的问题,官方没有说明,这里是基于折腾过的文章进行验证通过的。

主要原理就是,通过构建请求信息Request对象,将其注入到初始化的框架APP里面,要手动初始化框架,如果框架具备的上文,初始化后,通过app对象请求指定的方法和控制器,如此就有了下文。就可以通过下文返回得结果进行断言等操作。

研究thinkphp6的phpunit整合血泪史
https://blog.yongit.com/note/782453.html

首先安装 phpuint

composer require phpunit/phpunit --dev

1.测试控制器方法产出结果

<?php
declare (strict_types=1);
namespace tests;

final class DemoTest extends \PHPUnit\Framework\TestCase
{
    /**
     * 这里是测试控制的某个方法产出的结果
     * 
     * @test
     */
    public function testControllerDemo(): void
    {
        $request = new \app\Request();
        $request->setMethod('POST');
        
        // 路由地址
        $request->setUrl('/index/home');
        //$request->withGet(['xid' => 99,]);
        //$request->withPost(['aaa' => 111, 'bbb' => 222,]);
        $request->withHeader(['HTTP_ACCEPT' => 'application/json',]);
		
		// 初始化框架,并将请求信息类注入到框架里面
        $app = (new \think\App());
        $app->http->run($request);
		
		// 调用框架方法,这里可以按命名空间直接调用
        $userController = new UserController($app);
		// 请求接口的控制器方法
        $response = $userController->index();
		// 获取接口返回得body内容
        $content = $response->getContent();

		// 可以进行你的断言操作了
        $this->assertEquals("success", $content);
        
    }

    /**
     * @test
     */
    public function testDemo1(): void
    {
        //断言为真
        $this->assertTrue(true);
    }

}


在项目根目录下运行单元测试,指定文件:

php ./vendor/bin/phpunit tests/DemoTest.php

如果运行过程中不通,可能是你的php拓展缺乏,你的接口底层可能需要进行异常捕捉查看缺少了啥。

起飞,飞高点

composer加入tests目录命名空间
执行composer install 更新目录命名空间关联

"autoload": {
        "psr-4": {
            "app\\": "app",
            "tests\\": "tests"
        },
   
    },

按封装一个访问类

<?php

namespace tests\Library;

/**
 * Class TestExtend
 * @package tests\Library
 */
trait TestExtendTrait
{
    /**
     * 构造一个请求应用,测试控制器
     *
     * @param array $data 入参数组
     * @param string $method 请求方法
     * @return \think\App
     */
    function visitorJson($controller, $action, $data, $uid = null, $method = 'POST')
    {
        if (is_numeric($uid)) {

        }

        $app = new \think\App();

        #$app->request->setMethod($method);
        //$app->request->setController('Xlogin');
        //$app->request->setUrl('/index/debug/testing26');
        //$app->request->setUrl('/index/oauth/login');
        //$app->request->setBaseUrl('/index/oauth/login');

        $app->request->setUrl("/{$controller}/{$action}}");

        //$app->request->withGet(['xid' => 99,'xx' => 'get-xx','yy' => 'get-yy',]);
        //$app->request->withGet($data);
        //$app->request->withPost(['aaa' => 111, 'bbb' => 222,'xx' => 'post-xx','yy' => 'post-yy',]);
        #$app->request->withPost($data);

        $request = new \app\Request();
        $request->withPost($data);
        $request->withRoute($data); //tp6的bug啊,一行代码曲线救国

        $response = $app->http->run($request);
        //重置请求对象
        $app->request->setMethod($method);//非必须
        $app->request->setAction($action);
        //$app->request->withGet($data);
        //$app->request->withPost($data);
        //$response->send();
        $app->http->end($response);


        $controller = "\\app\\controller\\" . $controller;

        $test = new $controller($app);
        $result = $test->$action();
        $content = $result->getContent();

        return json_decode($content, true);
    }


}

自己封装一个trait类,用户use 方便调用
Demo:

 $content = $this->visitorJson($controller='User', $action='getGroupInfo', $params=['id' => 1111]);
 $this->assertNotEmpty($content['data'], 'user can not empty.');

这里就有疑问了,model层,service层怎么用?

由于这些内部层是无法直接被外部调用的,而controller之所以可以是因为注入了请求和响应,具有上下文关系,所以我们也要去框架内部实现一个上下文,比如底层controller提供一个调用model的方法或提供一个调用service的工厂方法,如此,可以获取app的时候,直接去调工厂方法来实现某个service,这里只提供一个思路,就不继续了,后续有空再补充。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值