如何测试我的phpspec测试中生成的内容类型?

时间:2016-01-21 04:23:35

标签: php phpspec

例如:

测试代码

function it_records_last_checked()
{
    $this->getWrappedObject()->setServiceLocator( $this->getServiceLocator() );
    $this->isAvailable( 'google.com' )->shouldReturn( false );

    /** @var Url $last */
    $last = $this->getLastChecked();
    $last->shoudHaveType( Url::class );
    $last->host->registrableDomain->shouldBeLike('google.com');
}

规范包装了一个代码为的对象:

namespace Application\Service;

use Application\Exception\DomainInvalidException;
use Application\Model\Whois;
use Pdp\Uri\Url;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
use Application\Exception\DomainRequiredException;

class DomainService implements ServiceLocatorAwareInterface{
    use ServiceLocatorAwareTrait;

    /** @var  Url */
    protected $last_checked;


    /**
     * @return Url
     */
    public function getLastChecked()
    {
        return $this->last_checked;
    }

    /**
     * @param Url $last_checked
     */
    public function setLastChecked( $last_checked )
    {
        $this->last_checked = $last_checked;
    }


    /**
     * Use available configuration to determine if a domain is available
     * @param $domain
     * @return bool
     * @throws DomainRequiredException
     * @throws \Exception
     */
    public function isAvailable($domain)
    {
        if( !$domain )
            throw new DomainRequiredException();

        $pslManager = new \Pdp\PublicSuffixListManager();
        $parser     = new \Pdp\Parser($pslManager->getList());
        $host       = 'http://' . $domain;

        if( !$parser->isSuffixValid( $host ) )
            throw new DomainInvalidException();

        $this->last_checked = $parser->parseUrl($host);
        $whois = new Whois($this->last_checked->host->registerableDomain);

        return $whois->isAvailable();
    }
}

该服务设置其last_checked成员,其类型我想测试,例如。它似乎没有返回一个包装对象,它返回实际的Pdp \ Uri \ Url实例。

编写测试的规则是什么,以确保我们得到包裹的对象(主题)?

谢谢!

1 个答案:

答案 0 :(得分:1)

您在测试此逻辑时遇到的困难是PhpSpec试图将您推向另一种设计。您的测试正在验证并依赖于6/7其他对象的行为/结构,这使得它更像是集成测试而不是单元测试(在PhpSpec中这样做是故意的)

我已经强调了其中一些依赖项:

<?php
public function isAvailable($domain)
{
    // Pdp\Parser instantiation and configuration
    $pslManager = new \Pdp\PublicSuffixListManager();
    $parser     = new \Pdp\Parser($pslManager->getList());

    // Validation and parsing of $domain into an Url object
    if( !$domain ) {
        throw new DomainRequiredException();
    }

    $host = 'http://' . $domain;

    if( !$parser->isSuffixValid( $host ) ) {
        throw new DomainInvalidException();
    }

    $this->last_checked = $parser->parseUrl($host);

    // The "isAvailable" check
    // This depends on `Pdp\Uri\Url\Host` (in addition to Whois and `Pdp\Uri\Url`
    $whois = new Whois($this->last_checked->host->registerableDomain);

    return $whois->isAvailable();
}

通过移动Pdp类的配置/实例化,并从Whois检查中拆分验证/解析逻辑,您可以快速找到一些更可测试的东西(但使用不太方便的API)

public function __construct(\Pdp\Parser $parser)
{
    $this->parser = $parser;
}

public function parseDomain($domain)
{
    if( !$domain ) {
        throw new DomainRequiredException();
    }

    $host = 'http://' . $domain;

    if( !$parser->isSuffixValid( $host ) )
        throw new DomainInvalidException();

    return $parser->parseUrl($host);
}

public function isAvailable(Url $domain)
{
    $whois = new Whois($domain->host->registerableDomain);

    return $whois->isAvailable();
}

但是,通过让Whois能够检查您的Url对象是否可用,并注入测试变得更加容易

class DomainParser
{
    // Pdp\Parser should be registered as a service
    public function __construct(\Pdp\Parser $parser)
    {
        $this->parser = $parser;
    }

    public function parseDomain($domain)
    {
        if( !$domain ) {
            throw new DomainRequiredException();
        }

        $host = 'http://' . $domain;

        if( !$parser->isSuffixValid( $host ) )
            throw new DomainInvalidException();

        return $parser->parseUrl($host);
    }
}

class Whois
{
    public function isUrlAvailable(Url $url)
    {
        // Whois logic
    }
}

class DomainService
{
    public function __construct(DomainParser $parser, Whois $whois)
    {
        $this->parser = $parser;
        $this->whois = $whois;
    }

    public function isAvailable($domain)
    {
        $url = $this->parser->parseDomain($domain);

        $this->last_checked = $url;

        return $this->whois->isUrlAvailable($url);
    }
}

通过这三个类,可以轻松进行单元测试DomainServiceDomainParserWhois可以使用其他策略进行模拟和测试(假设它与第三方系统进行通信)< / p>

e.g。

function let(DomainParser $parser, Whois $whois)
{
    $this->beConstructedWith($parser, $whois);
}

function it_shows_a_domain_is_available(
    DomainParser $parser,
    Whois $whois,
    Url $url
) {
    $parser->parseDomain('http://test.com')->willReturn($url);
    $whois->isUrlAvailable($url)->willReturn(true);

    $this->isAvailable('http://test.com')->shouldReturn(true);
}

function it_records_last_checked(
    DomainParser $parser,
    Whois $whois,
    Url $url
) {
    $parser->parseDomain('http://test.com')->willReturn($url);
    $whois->isUrlAvailable($url)->willReturn(true);

    $this->isAvailable('http://test.com');

    // Note that we don't validate any properties on Url, that is the
    // responsibility of the tests for DomainParser and the Url object itself
    $this->getLastChecked()->shouldReturn($url);
}