作为程序员一定要保持良好的睡眠,才能好编程

laravel单元测试功能测试

发布时间:2020-02-05


https://www.cnblogs.com/love-snow/articles/7641198.html


https://blog.csdn.net/weixin_30808575/article/details/94960928


https://learnku.com/articles/17529




单元测试:


image.png




创建&运行测试


在你的项目根目录,使用 Artisan 命令 make:test:


php artisan make:test UserTest // 在Feature目录下创建测试类(功能测试)
php artisan make:test UserTest --unit // 在Unit目录下创建测试类(单元测试)


如下:

<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->assertTrue(true);
    }
}


注:如果在测试类中定义了自己的 setUp 方法,确保在该方法中调用 parent::setUp()。


创建完测试类后,就可以像使用 PHPUnit 一样定义测试方法,要运行测试,只需在终端执行 phpunit 命令即可:、


注意:如果运行时出现 -bash: phpunit: command not found


命令改成:

vendor/bin/phpunit


运行单个测试示例:

vendor/bin/phpunit --filter=UserTest



更好的查看测试异常信息


在 app\Exceptions\Handler.php 中加上一行:


public function render($request, Exception $exception)
{
    if(app()->environment() === 'local') throw $exception;  // 此处加上一行
    // 注意,只有环境变量是 local 的时候才会加上这行,是不是也可以设定为 testing,教程上说不起作用,但是带上测试环境变量之后就可以使用 testing 啦!
    return parent::render($request, $exception);
}

也就是

APP_ENV=testing phpunit



创建便于测试的辅助函数


修改 composer.json 并导出自动加载文件


"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
    },
    "files":["tests/utilities/functions.php"]  -->这里增加一行
},


自动导入到composer

composer dump-autoload


将几个常用的函数封装到 functions.php 中去:


<?php
function create($class,$attributes = [])
{
    return factory($class)->create($attributes);
}
function make($class,$attributes = [])
{
    return factory($class)->make($attributes);
}
function raw($class,$attributes = [])
{
    return factory($class)->raw($attributes);
}




模型 create () 与 make () 方法的区别


create() 方法会得到一个实例,并将实例保存到数据库中;make() 方法只会得到一个实例。在本节的测试中我们不需要保存 $thread 实例,因为我们会在 RepliesController 的 store() 方法进行保存,故使用 make () 方法。


简单的说,当我们在编写测试用例的时候,如果是模拟用户填写表单的数据,那就不需要写入数据库中,也就是说,不需要使用 create() 方法,而只需要使用 make() 方法来创建即可。


create () 方法得到一个模型实例,并保存到数据库中;

make () 方法得到一个模型实例(不保存);

raw () 方法是得到一个模型实例转化后的数组。


/**
* Create a collection of models and persist them to the database.
*
* @param  array  $attributes
* @return mixed
*/
public function create(array $attributes = [])
{
$results = $this->make($attributes);
if ($results instanceof Model) {
    $this->store(collect([$results]));
} else {
    $this->store($results);
}
return $results;
}
/**
* Create a collection of models.
*
* @param  array  $attributes
* @return mixed
*/
public function make(array $attributes = [])
{
if ($this->amount === null) {
    return $this->makeInstance($attributes);
}
if ($this->amount < 1) {
    return (new $this->class)->newCollection();
}
return (new $this->class)->newCollection(array_map(function () use ($attributes) {
    return $this->makeInstance($attributes);
}, range(1, $this->amount)));
}







Laravel中单元测试的坑


使用Laravel 的你知道这个事情吗?

也许这只是我见识太少,对单元测试了解太少了!

今天在写自己小项目的单元测试时,遇到一个坑!~我登录后,想进行测试检测用户是否登录的操作!~ 

因为是登录后有进行用户信息缓存的,所以在检测是否登录时就是去缓存中进行查看,看是否有对应的Key的信息,如果有就将用户信息取出,并返回,如果没有则返回登录超时或未登录的响应。 

但是今天写了个单元测试,死活不通过测试!~


始终没有你想要的的结果:

比如说如下代码:


场景:

image.png

env文件中配置的是redis

image.png


看下面代码


cache()->put('user','james');
$val =  cache()->get('user');
var_dump($val);


那么这样的代码是可以顺利打印出  james


按道理来说应该存入到redis,是这样理解的,但是在 单元测试中,并没有存入到redis里。



//cache()->put('user','james');
$val =  cache()->get('user');
var_dump($val);

打印出来的结果是 NULL 



接着看为什么会是Null,通过 config() 函数获取到的  cache.default 的变量尽然是 array


$val = config('cache.default');
var_dump($val);

dd(cache()->getDefaultDriver());

在web访问、artisan 中 可以正常打印到  redis。


在单元测试中打印出的是 array? 


可是我在.env 中配置的CACHE_DRIVER 明明是redis啊!


最后我只能使出杀手锏,

通过项目查找 ,找到 phpunit.xml 中有对php的配置:


./config/cache.php:    'default' => env('CACHE_DRIVER', 'file'),

./phpunit.xml:        <env name="CACHE_DRIVER" value="array"/>



终于找到你:./phpunit.xml: <env name="CACHE_DRIVER" value="array"/> 


原来是phpunit.xml 配置文件指定了在测试用例中使用的CACHE_DRIVER为array!~ 


如图:

image.png


好吧,找到原因了,不然今晚估计睡不好了,哈哈! 

现在改完了这里,测试用例通过了所有测试,可以安心睡觉了!~



使用composer test 执行 phpunit


"scripts": {
    "test" : [
        "vendor/bin/phpunit"
    ],
    ... 
},


然后就可以使用  composer test 命令执行 phpunit了




单元测试断言


1 assertPageLoaded($uri, $message = null) //断言最后被加载的页面;如果加载失败抛出异常:$uri/$message
2 assertResponseOk() //断言客户端返回的响应状态码是否是200
3 assertReponseStatus($code) //断言客户端返回的响应状态码是否和给定码值相匹配
4 assertViewHas($key, $value = null) //断言响应视图包含给定数据片段
5 assertViewHasAll($bindings) //断言视图包含给定数据列表
6 assertViewMissing($key) //断言响应视图不包含给定数据片段
7 assertRedirectedTo($uri, $with = []) //断言客户端是否重定向到给定URI
8 assertRedirectedToRoute($name, $parameters = [], $with = []) //断言客户端是否重定向到给定路由
9 assertRedirectedToAction($name, $parameters = [], $with = []) //断言客户端是否重定向到给定动作
10 assertSessionHas($key, $value = null) //断言session包含给定键/值
11 assertSessionHasAll($bindings) //断言session包含给定值列表
12 assertSessionHasErrors($bindings = []) //断言session包含绑定错误
13 assertHasOldInput() //断言session中包含上一次输入



[root@localhost laravel_admin]# ./vendor/bin/phpunit
PHPUnit 7.5.11 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 122 ms, Memory: 12.00 MB

OK (3 tests, 3 assertions)
[root@localhost laravel_admin]#