国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

PHPUnit9.0 測(cè)試替身-Stubs(樁件)

2022-05-11 17:19 更新

將對(duì)象替換為(可選地)返回配置好的返回值的測(cè)試替身的實(shí)踐方法稱為打樁(stubbing)??梢杂脴都⊿tub)來(lái)“替換掉被測(cè)系統(tǒng)所依賴的實(shí)際組件,這樣測(cè)試就有了對(duì)被測(cè)系統(tǒng)的間接輸入的控制點(diǎn)。這使得測(cè)試能強(qiáng)制安排被測(cè)系統(tǒng)的執(zhí)行路徑,否則被測(cè)系統(tǒng)可能無(wú)法執(zhí)行”。

示例 8.2 展示了如何對(duì)方法的調(diào)用進(jìn)行上樁以及如何設(shè)定返回值。首先用 ?PHPUnit\Framework\TestCase? 類提供的 ?createStub()? 方法來(lái)建立一個(gè)樁件對(duì)象,它表面看起來(lái)像是 ?SomeClass? 類(示例 8.1)的實(shí)例。隨后用 PHPUnit 提供的流暢式接口來(lái)指定樁件的行為。本質(zhì)上,這意味著不需要建立多個(gè)臨時(shí)對(duì)象然后再把它們捆到一起。取而代之的是范例中所示的鏈?zhǔn)椒椒ㄕ{(diào)用。這使得代碼更加易讀并更加“流暢”。

示例 8.1 想要上樁的類

<?php declare(strict_types=1);
class SomeClass
{
    public function doSomething()
    {
        // 隨便做點(diǎn)什么。
    }
}

示例 8.2 對(duì)某個(gè)方法的調(diào)用進(jìn)行上樁,返回固定值

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // 配置樁件。
        $stub->method('doSomething')
             ->willReturn('foo');

        // 現(xiàn)在調(diào)用 $stub->doSomething() 會(huì)返回 'foo'。
        $this->assertSame('foo', $stub->doSomething());
    }

僅當(dāng)原始類中不包含名字為“method”的方法時(shí),以上范例才能正常運(yùn)行。
如果原始類包含名為“method”的方法,就必須用 ?$stub->expects($this->any())->method('doSomething')->willReturn('foo');?

“在幕后”,當(dāng)使用了 ?createStub()? 方法時(shí), PHPUnit 自動(dòng)生成了一個(gè)新的 PHP 類來(lái)實(shí)現(xiàn)想要的行為。
請(qǐng)注意:?createStub()? 會(huì)自動(dòng)遞歸地基于方法的返回類型對(duì)返回值進(jìn)行上樁??紤]以下示例:
示例 8.3 帶有返回類型聲明的方法

<?php declare(strict_types=1);
class C
{
    public function m(): D
    {
        // 隨便做點(diǎn)什么。
    }
}

在上述示例中,?C::m()? 方法具有返回類型聲明,指示此方法返回類型為 ?D? 的對(duì)象。那么,舉個(gè)例子說(shuō),創(chuàng)建 ?C? 的測(cè)試替身而又未用 ?willReturn()? 給 ?m()? 配置返回值時(shí),則當(dāng) PHPUnit 調(diào)用 ?m()? 時(shí)會(huì)自動(dòng)創(chuàng)建一個(gè) ?D ?的測(cè)試替身作為返回值。
類似地,如果 ?m ?的返回類型聲明是標(biāo)量類型,則會(huì)生成諸如 ?0?(對(duì)于 ?int?)、?0.0?(對(duì)于 ?float?)、或 ?[]?(對(duì)于 ?array?)這樣的返回值。
示例 8.4 展示了如何用仿件生成器的流暢式接口來(lái)配置測(cè)試替身的生成。這個(gè)測(cè)試替身的默認(rèn)配置用的是和 ?createStub()? 相同的最佳實(shí)踐。
示例 8.4 使用可用于配置生成的測(cè)試替身類的仿件生成器 API

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->getMockBuilder(SomeClass::class)
                     ->disableOriginalConstructor()
                     ->disableOriginalClone()
                     ->disableArgumentCloning()
                     ->disallowMockingUnknownTypes()
                     ->getMock();

        // 配置樁件。
        $stub->method('doSomething')
             ->willReturn('foo');

        // 現(xiàn)在調(diào)用 $stub->doSomething() 會(huì)返回 'foo'。
        $this->assertSame('foo', $stub->doSomething());
    }

在之前的例子中,用 ?willReturn($value) ?返回簡(jiǎn)單值。這個(gè)簡(jiǎn)短的語(yǔ)法相當(dāng)于 ?will($this->returnValue($value))?。而在這個(gè)長(zhǎng)點(diǎn)的語(yǔ)法中,可以使用變量,從而實(shí)現(xiàn)更復(fù)雜的上樁行為。
有時(shí)想要將(未改變的)方法調(diào)用時(shí)所使用的參數(shù)之一作為樁件的方法的調(diào)用結(jié)果來(lái)返回。示例 8.5 展示了如何用 ?returnArgument()? 代替 ?returnValue()? 來(lái)做到這點(diǎn)。
示例 8.5 對(duì)某個(gè)方法的調(diào)用進(jìn)行上樁,返回參數(shù)之一

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testReturnArgumentStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // 配置樁件。
        $stub->method('doSomething')
             ->will($this->returnArgument(0));

        // $stub->doSomething('foo') 返回 'foo'
        $this->assertSame('foo', $stub->doSomething('foo'));

        // $stub->doSomething('bar') 返回 'bar'
        $this->assertSame('bar', $stub->doSomething('bar'));
    }
}

在用流暢式接口進(jìn)行測(cè)試時(shí),讓某個(gè)已上樁的方法返回對(duì)樁件對(duì)象的引用有時(shí)會(huì)很有用。示例 8.6 展示了如何用 ?returnSelf()? 來(lái)做到這點(diǎn)。
示例 8.6 對(duì)方法的調(diào)用進(jìn)行上樁,返回對(duì)樁件對(duì)象的引用

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testReturnSelf(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // 配置樁件。
        $stub->method('doSomething')
             ->will($this->returnSelf());

        // $stub->doSomething() 返回 $stub
        $this->assertSame($stub, $stub->doSomething());
    }
}

有時(shí)候,上樁的方法需要根據(jù)預(yù)定義的參數(shù)清單來(lái)返回不同的值??梢杂??returnValueMap()? 方法將參數(shù)和相應(yīng)的返回值關(guān)聯(lián)起來(lái)建立映射。示例參見(jiàn)示例 8.7。
示例 8.7 對(duì)方法的調(diào)用進(jìn)行上樁,按照映射確定返回值

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testReturnValueMapStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // Create a map of arguments to return values.
        $map = [
            ['a', 'b', 'c', 'd'],
            ['e', 'f', 'g', 'h']
        ];

        // 配置樁件。
        $stub->method('doSomething')
             ->will($this->returnValueMap($map));

        // $stub->doSomething() 根據(jù)提供的參數(shù)返回不同的值。
        $this->assertSame('d', $stub->doSomething('a', 'b', 'c'));
        $this->assertSame('h', $stub->doSomething('e', 'f', 'g'));
    }
}

如果上樁的方法需要返回計(jì)算得到的值而不是固定值(參見(jiàn) ?returnValue()?)或某個(gè)(未改變的)參數(shù)(參見(jiàn) ?returnArgument()?),可以用 ?returnCallback()? 來(lái)讓上樁的方法返回回調(diào)函數(shù)或方法的結(jié)果。示例參見(jiàn)示例 8.8。
示例 8.8 對(duì)方法的調(diào)用進(jìn)行上樁,由回調(diào)生成返回值

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testReturnCallbackStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // 配置樁件。
        $stub->method('doSomething')
             ->will($this->returnCallback('str_rot13'));

        // $stub->doSomething($argument) 返回 str_rot13($argument)
        $this->assertSame('fbzrguvat', $stub->doSomething('something'));
    }
}

相比于建立回調(diào)方法,有一個(gè)更簡(jiǎn)單的選擇是直接給出期望返回值的列表。可以用 ?onConsecutiveCalls()? 方法來(lái)做到這個(gè)。示例參見(jiàn)示例 8.9。
示例 8.9 對(duì)方法的調(diào)用上樁,按照指定順序返回列表中的值

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testOnConsecutiveCallsStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // 配置樁件。
        $stub->method('doSomething')
             ->will($this->onConsecutiveCalls(2, 3, 5, 7));

        // $stub->doSomething() 每次都會(huì)返回不同的值
        $this->assertSame(2, $stub->doSomething());
        $this->assertSame(3, $stub->doSomething());
        $this->assertSame(5, $stub->doSomething());
    }
}

除了返回一個(gè)值之外,上樁的方法還能拋出一個(gè)異常。示例 8.10 展示了如何用 ?throwException()? 做到這點(diǎn)。
示例 8.10 對(duì)方法的調(diào)用進(jìn)行上樁,拋出異常

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class StubTest extends TestCase
{
    public function testThrowExceptionStub(): void
    {
        // 為 SomeClass 類創(chuàng)建樁件。
        $stub = $this->createStub(SomeClass::class);

        // 配置樁件。
        $stub->method('doSomething')
             ->will($this->throwException(new Exception));

        // $stub->doSomething() 拋出異常
        $stub->doSomething();
    }
}

另外,也可以自行編寫(xiě)樁件,并在此過(guò)程中改善設(shè)計(jì)。在系統(tǒng)中被廣泛使用的資源是通過(guò)單個(gè)外觀(facade)來(lái)訪問(wèn)的,因此就能用樁件替換掉資源。例如,將散落在代碼各處的對(duì)數(shù)據(jù)庫(kù)的直接調(diào)用替換為單個(gè) ?Database ?對(duì)象,這個(gè)對(duì)象實(shí)現(xiàn)了 ?IDatabase ?接口。接下來(lái),就可以創(chuàng)建實(shí)現(xiàn)了 ?IDatabase ?的樁件并在測(cè)試中使用之。甚至可以創(chuàng)建一個(gè)選項(xiàng)來(lái)控制是用樁件還是用真實(shí)數(shù)據(jù)庫(kù)來(lái)運(yùn)行測(cè)試,這樣測(cè)試就既能在開(kāi)發(fā)過(guò)程中用作本地測(cè)試,又能在實(shí)際數(shù)據(jù)庫(kù)環(huán)境中進(jìn)行集成測(cè)試。
需要上樁的功能往往集中在同一個(gè)對(duì)象中,這就改善了內(nèi)聚度。將功能通過(guò)單一且一致的接口呈現(xiàn)出來(lái),就降低了這部分與系統(tǒng)其他部分之間的耦合度。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)