1

我有这样的功能:

class Bar{
    public function a():Foo{
    .
    .
    .
    }
}

现在我正在尝试使用 php 单元测试为类 Bar 创建一个模拟

    $mockedBar = $this->getMockBuilder(Bar::class)
     ->getMock()
     ->method('a')
     ->willReturn(new FakeFoo());

但是当我调用方法a时,我收到一个错误,即方法a返回类型必须是 Foo 的实例而不是 Mocked_blahblah。

不幸的是,类 Bar 不使用任何接口,系统非常大,我无法创建接口,因为它在我的代码中进行了巨大的重构;有没有办法a在模拟对象中禁用函数的返回类型?我正在使用 php7.2 和 phpunit 6.0.13。这是一个真实的场景:

class A
{
    public function b():B
    {
        echo "i am from class A function b";
    }
}
class B
{

}

class FakeB
{
}
class ATest extends TestCase
{
    public function testSayHi(){
        $mockedA = $this->getMockBuilder(A::class)
            ->getMock();
        $mockedA->method('b')->willReturn(new FakeB());
        $mockedA->b();
    }
}
4

1 回答 1

1

您不能禁用返回类型。也许您可以尝试使用某种骇人听闻的错误处理程序来做到这一点,但这是一件疯狂的事情。

好消息是您不会尝试做任何不寻常的事情,并且您的测试可以修复。

首先,您需要将结果分配getMock给一个变量。接下来,您可以定义您的测试替身:

class MyTest extends TestCase
{
    public function testIt()
    {
        $mockedBar = $this->getMockBuilder(Bar::class)->getMock();
        $mockedBar
             ->method('a')
             ->willReturn(new FakeFoo());

        $this->assertInstanceOf(Foo::class, $mockedBar->a());
    }
}

这仅适用FakeFoo于 类型Foo,例如扩展它:

class FakeFoo extends Foo
{
    // override any Foo methods you'd like to fake
}

你不需要自己创建一个 Fake,你可以使用 PHPUnit 创建一个 dummy:

class MyTest extends TestCase
{
    public function testIt()
    {
        $mockedBar = $this->createMock(Bar::class);
        $mockedBar
             ->method('a')
             ->willReturn($this->createMock(Foo::class));

        $this->assertInstanceOf(Foo::class, $mockedBar->a());
    }
}

要修复您的第二个示例:

class A
{
    public function b():B
    {
        echo "i am from class A function b";
    }
}

class B
{
}

class FakeB extends B
{
}

class ATest extends TestCase
{
    public function testSayHi(){
        $mockedA = $this->getMockBuilder(A::class)->getMock();
        $mockedA->method('b')->willReturn(new FakeB());
        $mockedA->b();
    }
}

或者,不要使用假的让 phpunit 处理它:

class ATest extends TestCase
{
    public function testSayHi(){
        $mockedA = $this->getMockBuilder(A::class)->getMock();
        $dummyB = $this->createMock(B::class);

        $mockedA->method('b')->willReturn($dummyB);
        $mockedA->b();
    }
}
于 2018-02-08T11:49:14.707 回答