在模拟命名空间和原始命名空间中创建模拟 phpunit 差异
creating mock phpunit discrepency in mocked namespace and the original one
我有这样的功能:
class Bar{
public function a():Foo{
.
.
.
}
}
现在我正在尝试使用 php 单元测试
为 class 栏创建一个模拟
$mockedBar = $this->getMockBuilder(Bar::class)
->getMock()
->method('a')
->willReturn(new FakeFoo());
但是当我调用方法 a
时出现错误,方法 a
return 类型必须是 Foo 的实例而不是 Mocked_blahblah.
不幸的是class Bar 不使用任何接口,系统非常大,我无法创建接口,因为它在我的代码中进行了大量重构;
有什么方法可以在模拟对象中禁用 return 类型的函数 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();
}
}
您无法禁用 return 类型。也许您可以尝试使用某种 hackish 错误处理程序来完成它,但这样做是一件疯狂的事情。
好消息是您没有尝试做任何不寻常的事情,您的测试可以修复。
首先,您需要将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 创建一个虚拟对象:
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();
}
}
我有这样的功能:
class Bar{
public function a():Foo{
.
.
.
}
}
现在我正在尝试使用 php 单元测试
为 class 栏创建一个模拟 $mockedBar = $this->getMockBuilder(Bar::class)
->getMock()
->method('a')
->willReturn(new FakeFoo());
但是当我调用方法 a
时出现错误,方法 a
return 类型必须是 Foo 的实例而不是 Mocked_blahblah.
不幸的是class Bar 不使用任何接口,系统非常大,我无法创建接口,因为它在我的代码中进行了大量重构;
有什么方法可以在模拟对象中禁用 return 类型的函数 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();
}
}
您无法禁用 return 类型。也许您可以尝试使用某种 hackish 错误处理程序来完成它,但这样做是一件疯狂的事情。
好消息是您没有尝试做任何不寻常的事情,您的测试可以修复。
首先,您需要将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 创建一个虚拟对象:
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();
}
}