我是测试新手,我正在尝试创建一个单元测试来覆盖 NewsCreator create 方法中的第一个 if 语句。
这个问题有两个部分。
首先:我应该如何实例化 NewsCreator 来处理模拟的验证器和存储库?
第二:测试这条路径的正确方法是什么?
这是调用需要测试的类的 Controller 方法:
public function store()
{
$creator = new NewsCreator($this);
return $creator->create(Input::all());
}
这是我想测试的类,NewsCreator:
<?php namespace WHS\Portal\News;
class NewsCreator {
protected $listener;
protected $repository;
protected $validator;
protected $errors;
public function __construct($listener, NewsRepositoryInterface $repository, NewsValidator $validator)
{
$this->listener = $listener;
$this->repository = $repository;
$this->validator = $validator;
$this->errors = [];
}
public function create($data)
{
if($this->validator->fails($data))
{
return $this->listener->newsCreationFails($this->validator->messages());
}
if($this->repository->create($data))
{
return $this->listener->newsCreationSucceeds();
}
return $this->listener->newsCreationFails($this->errors);
}
}
这是我尝试编写的测试,但它失败了 有异常(exception):
2) WHS\Portal\Tests\News\NewsCreatorTest::test_failed_validation Mockery\Exception\InvalidCountException:方法 fails("foo") from Mockery_1_WHS_Portal_News_NewsValidator 应该调用 1 次但调用 0 次。
<?php namespace WHS\Portal\Tests\News;
use TestCase;
use Mockery as m;
class NewsCreatorTest extends TestCase {
public function tearDown()
{
m::close();
}
public function test_failed_validation()
{
$newsRepo = m::mock('\WHS\Portal\News\DbNewsRepository["create"]');
$newsValidator = m::mock('\WHS\Portal\News\NewsValidator["fails"]');
$listener = new NewsListenerStub();
$listener = m::mock($listener)->makePartial();
$newsValidator->shouldReceive('fails')->with('foo')->once()->andReturn(true);
$listener->shouldReceive('newsCreationFails')->once()->with('foo')->andReturn();
$newsCreator = new \WHS\Portal\News\NewsCreator($listener,$newsRepo,$newsValidator);
$newsCreator->create([]);
}
}
更新测试:
use TestCase;
use Mockery as m;
class NewsCreatorTest extends TestCase {
public function tearDown()
{
m::close();
}
public function test_failed_validation()
{
$newsRepo = m::mock('\WHS\Portal\News\DbNewsRepository["create"]');
$newsValidator = m::mock('\WHS\Portal\News\NewsValidator["fails"]');
$listener = m::mock('\WHS\Portal\Tests\News\NewsListenerStub["newsCreationFails"]');
$newsValidator->shouldReceive('fails')->with([])->once()->andReturn(true);
$newsValidator->shouldReceive('messages')->once();
$listener->shouldReceive('newsCreationFails')->once()->with('foo')->andReturn('foo-bar');
$newsCreator = new \WHS\Portal\News\NewsCreator($listener,$newsRepo,$newsValidator);
$result = $newsCreator->create([]);
$this->assertEquals('foo-bar', $result);
}
}
stub 类:
class NewsListenerStub
{
public function newsCreationFails($data)
{
return $data;
}
}
请帮忙。
谢谢。
最佳答案
fails()
方法在您的类中使用$data
参数调用。
在您的单元测试中,您传入一个空数组作为数据 create([])
。
您对 validatorMock 的参数期望是期望使用参数 foo
调用 fails()
。您必须更改它以匹配空数组。
$newsValidator->shouldReceive('fails')->with([])->once()->andReturn(true);
您还必须在 validatorMock 上指定 validator->messages()
方法,因为它也在您的类中被调用。
$newsValidator->shouldReceive('messages')->once();
要使此测试真正有意义,您必须断言 NewsCreationFails
的结果与 create()
的返回值匹配。
$listener->shouldReceive('newsCreationFails')->once()->with('foo')->andReturn('foo-bar');
...
$result = $newsCreator->create([]);
$this->assertEquals('foo-bar', $result);
关于php - 使用 mock 对具有依赖关系的类进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21807656/