jasny/phpunit-extension 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

jasny/phpunit-extension

最新稳定版本:v0.5.1

Composer 安装命令:

composer require jasny/phpunit-extension

包简介

Additional functionality for PHPUnit (callback mock, expected warning, ...)

README 文档

README

Build status Scrutinizer Code Quality Code Coverage Packagist Stable Version Packagist License

Additional functionality for PHPUnit.

Installation

composer require jasny/phpunit-extension

Usage

Callback mock

MockObject createCallbackMock(InvocationOrder $matcher, array|Closure $assert = null, $return = null)

The method takes either the expected arguments as array and the return value or a Closure. If a Closure is given, it will be called with an InvocationMocker, which can be used for more advanced matching.

use Jasny\PHPUnit\CallbackMockTrait;
use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use CallbackMockTrait;
    
    public function testSingleCall()
    {
        $callback = $this->createCallbackMock($this->once(), ['abc'], 10);
        function_that_invokes($callback);
    }

    public function testConsecutiveCalls()
    {
        $callback = $this->createCallbackMock(
            $this->exactly(2),
            function(InvocationMocker $invoke) {
                $invoke
                    ->withConsecutive(['abc'], ['xyz'])
                    ->willReturnOnConsecutiveCalls(10, 42);
            }
        );

        function_that_invokes($callback);
    }
}

Safe Mocks

The SafeMocksTrait overwrites the createMock method to disable auto-return value generation. This means that the test will fail if any method is called that isn't configured.

use Jasny\PHPUnit\SafeMocksTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use SafeMocksTrait;
    
    public function test()
    {
        $foo = $this->createMock(Foo::class);
        $foo->expects($this->once())->method('hello');
    
        $foo->hello();
        $foo->bye();
    }
}

In the example above, the method bye() isn't configured for $foo. Normally the test would succeed, but with SafeMocksTrait this test will result in the failure

Return value inference disabled and no expectation set up for Foo::bye()

Expected warning

ExpectedWarningTrait overwrites the following methods;

  • expectNotice()
  • expectNoticeMessage(string $message)
  • expectNoticeMessageMatches(string $regexp)
  • expectWarning()
  • expectWarningMessage(string $message)
  • expectWarningMessageMatches(string $regexp)
  • expectDeprecation()
  • expectDeprecationMessage(string $message)
  • expectDeprecationMessageMatches(string $regexp)

Take the following example function;

function my_old_func(float $a)
{
    trigger_error("Use my_new_func() instead", E_USER_DEPRECATED);
    return (int)($a * 100);
}

PHPUnit converts notices and warning to exceptions. While you can catch these exceptions through methods like expectDeprecation, any code after the the notice/warning isn't run and therefor untestable.

The following test succeeds, while it should fail.

use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    public function test()
    {
        $this->expectDeprecation();
    
        $result = my_old_func(0.42); // <-- Will exit on deprecation

        $this->assertEquals(89, $result); // This should fail, but is never executed
    }
}

ExpectedWarningTrait sets a custom error handler, that catches expected warnings and notices, without converting them to exceptions. Code will continue to run.

After all other assertions succeed, the code will check if there are any expected warnings/notices that haven't been triggered.

use Jasny\PHPUnit\ExpectWarningTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use ExpectWarningTrait;

    public function test()
    {
        $this->expectDeprecation();
    
        $result = my_old_func(0.42); // <-- Will NOT exit

        $this->assertEquals(89, $result); // Will fail
    }
}

In context of

mixed inContextOf(object $object, \Closure $function)

The function is called in context of the given object. This allows to call private and protected methods and get or set private and protected properties.

use Jasny\PHPUnit\InContextOfTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use InContextOfTrait;
    
    public function testCallPrivateMethod()
    {
        $object = new MyObject();
    
        $result = $this->inContextOf($object, fn($object) => $object->privateMethod('foo', 'bar'));
        $this->assertEquals($result, 'foo-bar');
    }
    
    
    public function testGetPrivateProperty()
    {
        $value = $this->inContextOf($object, fn($object) => $object->privateProperty);
        $this->assertEquals($value, 999);
    }
    
    
    /** Alternatively, do the assertion in the closure */
    public function testAssertPrivateProperty()
    {
        $this->inContextOf($object, fn($object) => $this->assertEquals($object->privateProperty, 999));
    }

    public function testSetPrivateProperty()
    {
        $this->inContextOf($object, fn($object) => $object->privateProperty = 42);
    }
}

Beware: You should only test via public methods and properties. When you're required to access private methods or properties to perform tests, something is likely wrong in the architecture of your code.

Consecutive calls

ConsecutiveTrait is a replacement for PHPUnit's withConsecutive method which was removed in PHPUnit 10.

use Jasny\PHPUnit\ConsecutiveTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use ConsecutiveTrait;

    public function test()
    {
        $mock = $this->createMock(MyClass::class);
        $mock->expects($this->exactly(2))
            ->method('foo')
            ->with(...$this->consecutive(
                ['a', 1],
                ['b', 2],
            ))
            ->willReturnOnConsecutiveCalls(10, 42);
        
        $this->assertEquals(10, $mock->foo('a', 1));
        $this->assertEquals(42, $mock->foo('b', 2));
    }
}

统计信息

  • 总下载量: 4.89k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 0
  • 依赖项目数: 8
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-09-15