浅谈 laravel 的测试用例编写

1,645 阅读1分钟

开篇

因为自身之前基本没写过什么单元测试用例, 感觉是一大憾事, 计划在接下来需求中, 体验下 TDD 方式编程, 特此做了一次简单的笔记.

因为我们使用的laravel框架, 在底层已经帮我们实现了很多细节的东西, 无缝集成了 PHPUnit, 所以使用起来还是比较简单的.

简单例子

如果构造我们的数据

我们的业务代码中经常有需要直接查业务库、操作库的需求, 如果经常的改变数据库数据, 好多时候因为数据不到位, 多表逻辑的话更改繁琐

修改业务代码逻辑, 提交代码还需要将测试代码移除, 过程容易将调试代码提交上线

如何在测试用例中避免数据干扰, 只专心关注代码逻辑, 推荐使用 laravel 的 Mockery::mock, 无侵入性设置返回值.

1. 首先我们封装个设置 mock 的类

所有的需要mock的方法, 都需要初始化称 mock 对象

protected function initMock($class)
{
    $mock = \Mockery::mock($class);
    $this->app->instance($class, $mock);
    return $mock;    
}

2. 在执行service之前, 一定要先 mock 下指定的类来

这里我们mock初始化了 ClueRepository 类

$this->clueRepository = $this->initMock(\xx\ClueRepository::class);

3. 设置 mock 的类执行次数一次方法指定返回值为 20

使用上一步骤 mock 对象, 设置调用一次 getClueTotal 方法, 返回20数值

$this->clueRepository->shouldReceive('getClueTotal')
            ->once()
            ->andReturn(20);

4. 绑定我们要测试的 service 类

获取service的对象

$this->clueRecommendService = app(\xx\ClueRecommendService::class);

5. 执行真正的业务逻辑

$ret = $this->clueRecommendService->claimRecommendClue(['sale_uid' => 111, 'clue_id' => 2]);

6. 验证返回值

验证传入和传出是否一致

$this->assertEquals($this->saleUid, $ret['sale_uid']);
$this->assertEquals($this->clueId, $ret['clue_id']);

7. 执行测试用例

vendor/bin/phpunit tests/ExampleTest.php

异常

异常可以在方法上增加注释使用

/**
 * @expectedException Exception
 * @expectedExceptionCode 136
 * @expectedExceptionMessage 线索
 *
 * @throws Exception
 */

声明上个方法依赖, return返回值, 作为此方法的参数

/**
 * 声明依赖上个方法
 * @depends testBasicExample
 *
 */
public function testGetClueInfoService(array $ret)
{
    $this->assertTrue(true);
}

构造测试数组

$data = [
    'name' => 'ttt',
    'data' => [
        'test' => '小明',
    ],
];

一些常用方法

//跳过当前方法执行结果
 $this->markTestSkipped();
 
 //在数组中判定外层test是否存在 
 $this->assertArrayHasKey('test', $data); #false  
 
 //查找最外层值是否存在
 $this->assertContains('ttt', $data); #true 

更多方法: www.phpunit.cn/manual/4.8/…