【问题标题】:Phpunit, Dependency Injection, test stubs: inject mock, or anonymus object?Phpunit,依赖注入,测试存根:注入模拟或匿名对象?
【发布时间】:2019-11-27 22:03:12
【问题描述】:

我有点怀疑要注入什么。鉴于此代码:

class A
{
    public function getSomething()
    {
        return 'something';
    }
}

class TestMe
{
    /**
     * @var A
     */
    private $a;

    public function __construct($a)
    {
        $this->a = $a;
    }

    public function greetings()
    {
        return 'Hello, '.$this->a->getSomething();
    }
}

我的测试 A:

function testA()
{
    $a = new class() {
        public function getSomething()
        {
            return 'aAnonimus';
        }
    };

    $sut = new TestMe($a);

    $this->assertEquals($sut->greetings(), 'Hello, aAnonimus');
}

testB,相同但带有模拟:

function testA()
{
    $a = $this->createMock(A::class);
    $a->method('getSomething')->willReturn('bMockery');

    $sut = new TestMe($a);

    $this->assertEquals($sut->greetings(), 'Hello, bMockery');
}

在第一个测试中,我只是注入了一个普通对象。 但第二种方式更像是 Phpunit 的方式:使用模拟对象。

问题是,在很长一段时间内,哪一个赢了?我发现第一个更方便,第二个测试,你必须知道依赖的类名(否则你不能创建一个模拟)

【问题讨论】:

  • 任何人“知道依赖的类名”有什么问题?
  • 因为如果它改变了,测试也应该。
  • hmm... 换一种看法如何:您需要更改某些依赖项-> 在测试用例中设置它-> 在源代码中更改它?我的意思是 2 点:a)您通常不会在您的课程中使用随机依赖项,​​是吗?你需要特定的、可预期的和可靠的; b)是的,源代码和测试代码具有某种相关性,它们相互遵循(没有人想要不相关的测试)。并且从技术上考虑类型提示的依赖项——无论如何你都需要扩展匿名类 === 'know the class name'。
  • 从长远来看,phpunit 方式绝对是最好的选择。您可以将expects 添加到它以确保实际调用它。您可以将with 添加到它以确保使用正确的变量调用它。如果函数被多次调用,您可以使用willReturnOnConsecutiveCalls 使其返回不同的值。

标签: unit-testing mocking phpunit


【解决方案1】:

从长远来看,第二种方式更好,因为在构造函数中最好有类型提示,这将不允许您提供简单的对象。 此外,当我们谈论 UnitTests 时,您应该测试某个类,而不依赖于 3rd 方库或其他服务逻辑。所以最好的方法是对所有属于测试类的服务使用模拟

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多