PHPUnit踩坑实录

版本信息 说明:现有项目使用php7.2, 只能支持phpunit8.5, 不支持部分新特性

php 7.4.30 phpunit 9.5.21 mockery 1.5.0 日常开发 测试类继承 PHPUnit\Framework\TestCase use PHPUnit\Framework\TestCase;

class BackBlackServiceTest extends TestCase{}

测试方法 public function testBackBlackService($data, $expect), 需是public, 以test开头

多用例可使用注解 @dataProvider dataProvider dataProvider 方法需为public, 参数个数,类型可按需自定义

$datamock[myFunc=>'myFuncExpectData']

public function serviceProvider() {

r]e;t''urn[12''==>>[[$$ddaattaa,,$$eexxppeecctt]],

}

断言时可增加用例名作为报错message

publicfunctiontestBackBlackService(){

this−>assertEquals(this->assertEquals(this−>assertEquals(expected, $actual, $this->getName());

}

常用技巧 对象mock(原则上需要mock的类为操作db,调用第三方服务的类) 可注入对象使用一般方法 \Mockery::mock(MyClass::class)

使ov(erlo\\aMMdoo:,cckkeearrlyyi::a::smm:oo)cckk((""oavleirals使o:a"d:."M.yCMlyaCslsa:s:sc:l:acslsa)s;s);
  • @runInSeparateProcess
  • @runTestsInSeparateProcesses
  • @preserveGlobalState disabled

使用shouldReceive定义mock方法,返回值 \Mockery::mock(“alias:” . MyClass::class)->shouldReceive(‘myFunc’)->andReturn($data[‘myFunc’] ?? []);

replyValidation−>shouldReceive(′valiate′)−>andThrow(newValidException(replyValidation->shouldReceive(‘valiate’)->andThrow(new ValidException(replyValidation−>shouldReceive(′valiate′)−>andThrow(newValidException(data[‘validate’])); //需要抛异常

多用例时需增加Mockery::close()方法 public function tearDown(): void { parent::tearDown(); Mockery::close(); }

特殊技巧 链式操作 person=ResumeService::module(′base′)−>findbyuserid((int)person = ResumeService::module(‘base’)->find_by_user_id((int)person=ResumeService::module(′base′)−>findb​yu​seri​d((int)userId); $resume_service->shouldReceive(‘module->find_by_user_id’) 同一个方法调用多次 参数区分 withAnyArgs() 任意传参

\aatMttioLMmceoekassest(rt(3y()):w)-:i->st>tphtiy(im(.me'.esa.s(l$(2ia2)ar)sg:s').Con\fMiogc:k:ecrlya:s:ss)p-y>(s'haoluiladsR:e'ce.ivCeo(n'fgiegt:C:ocnlfaisgsI)t-e>ms'h)o-u>ladtRLeecaesitv(e)(-'>gteitmCeosn(f2i)g-I>taenmd'R)e-t>uwrint(h$(d"aat"a)1-,>a$nddaRteat2u)r;n($data1);

静态常量 使用“alias:” mock的类无法访问该类的常量,静态变量

使用自定义类,方式注入

class ConstMap { public const CONTRACT_RESUME = ‘View’; //简 public static $remain_field = ‘SurplusNum’;

}

\Mockery::mock(‘alias:’ . ContractService::class, ConstMap::class);

魔术方法 类里面未定义属性,使用魔术方法__get($name) 访问

\Mockery::mock(‘overload:’ . CompanyComponent::class)->shouldReceive(’__construct’)->andSet(‘company_name’, ‘公司名’);

代码注解使用 通过phpunit.xml 定义,测试用例常量 如 inPhpUnit 跳过测试用例无法覆盖代码, 如register_shutdown_function !defined(‘inPhpUnit’) && register_shutdown_function(function(){});

使用注解跳过相关代码块覆盖 // @codeCoverageIgnoreStart

/@codeCoverageIgnoreEnd

phpunit.xml phpunit.xml (phpunit9) 关注参数 forceCoversAnnotation=“false”

<coverage></coverage>

xml version=“1.0” encoding=“UTF-8”?

src

tests

phpunit.xml (phpunit8.5) 关注参数 forceCoversAnnotation=“false”

<whitelist></whitelist>

xml version=“1.0” encoding=“UTF-8”?

tests

src

IDE支持 点选phpunit.xml, 或者指定用例, 更多运行/调试,使用覆盖率运行

命令行 全部覆盖率

pphhpp--ddxxddeebbuugg..mmooddee==ccoovveerraaggee//UUsseerrss//************//ccoommppoosseerr//vveennddoorr//pphhppuunniitt//pphhppuunniitt//pphhppuunniitt--ccoonnffiigguurraattiioonnpphhppuunniitt..xxmmlltests/unit/Service/Resume/KickFavoriteServiceTest.php

开发建议 db层不封装业务逻辑

mock便

相关文档 https://phpunit.readthedocs.io/en/9.5/

https://phpunit.readthedocs.io/zh_CN/latest/ (中文文档相对滞后)

http://docs.mockery.io/en/latest/index.html

下一篇

### 阿里云盘 挂载本地挂载