例如:
测试代码
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实例。
编写测试的规则是什么,以确保我们得到包裹的对象(主题)?
谢谢!
答案 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);
}
}
通过这三个类,可以轻松进行单元测试DomainService
和DomainParser
,Whois
可以使用其他策略进行模拟和测试(假设它与第三方系统进行通信)< / 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);
}