简体   繁体   English

PHP 单元测试 Mocking 成员变量依赖

[英]PHP Unit Test Mocking a member variable dependency

Hello lets say I want to test the function run from Class A and I'm using Mockery to mock external dependencies:你好,假设我想测试从 A 类运行的函数,我正在使用Mockery来模拟外部依赖项:

class A {
    protected myB;

    public function __construct(B $param) {
      $this->myB = $param;
    }

    protected function doStuff() {
      return "done";
    }

    public function run() {
      $this->doStuff();

      $this->myB->doOtherStuff();

      return "finished";
    }
}

class B {
    public function doOtherStuff() {
      return "done";
    }
}

So I wrote the test like this:所以我写了这样的测试:

public function testRun() {
    $mockB = Mockery::mock('overload:B');
    $mockB->shouldReceive('doOtherStuff')
        ->andReturn("not done");

    $mockA = Mockery::mock(A::class)->makePartial()->shouldAllowMockingProtectedMethods();
    $mockA->shouldReceive('doStuff')->andReturns("done");
    
    $mockA->run();
}

This throws me an exception like this: Error: Call to a member function doStuff() on null这会给我一个这样的异常:错误:在 null 上调用成员函数 doStuff()

I tried diffrent variations of mocking the internal dependency B which is getting called in the run function but I always endend up in an exception.我尝试了模拟内部依赖项 B 的不同变体,它在运行函数中被调用,但我总是以异常告终。

What am I doing wrong here?我在这里做错了什么?

Don't mock the thing you are testing.不要嘲笑你正在测试的东西。 Inject the mocked B into A .将模拟的B注入A

    public function testRun()
    {
        // Arrange
        $mockB = Mockery::mock(B::class);
        $a = new A($mockB);

        // Assert
        $mockB->shouldReceive('doOtherStuff')
            ->once()
            ->andReturn("not done");

        // Act
        $a->run();
    }

If you want to monkey patch A , you can still pass the mocked B in ( more details: constructor arguments in mockery ):如果你想给A补丁,你仍然可以将模拟的B传入( 更多细节:mockery 中的构造函数参数):

    public function testRun()
    {
        // Arrange
        $mockB = Mockery::mock(B::class);
        $a     = Mockery::mock(A::class, [$mockB])
            ->makePartial()
            ->shouldAllowMockingProtectedMethods();
        $a->shouldReceive('doStuff')
            ->andReturns('mocked done');

        // Assert
        $mockB->shouldReceive('doOtherStuff')
            ->once()
            ->andReturn('not done');

        // Act
        $a->run();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM