我是测试的新手,我正在尝试创建一个单元测试,它涵盖了NewsCreator创建方法中的第一个if语句。
这个问题有两个部分。
首先:我应该如何实例化NewsCreator来处理模拟的验证器和存储库?
第二:测试这条路径的正确方法是什么?
这是我的控制器方法,它调用需要测试的类:
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);
}
}
这是我试图写的测试,但它失败了 例外:
2) WHS\Portal\Tests\News\NewsCreatorTest::test_failed_validation Mockery\Exception\InvalidCountException: Method fails("foo") from Mockery_1_WHS_Portal_News_NewsValidator should be called exactly 1 times but called 0 times.
<?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);
}
}
存根类:
class NewsListenerStub
{
public function newsCreationFails($data)
{
return $data;
}
}
请帮忙。
感谢。
答案 0 :(得分:1)
使用类中的fails()
参数调用方法$data
。
在您的单元测试中,您将传入一个空数组作为数据create([])
。
您对validatorMock的参数期望是期望使用参数fails()
调用foo
。你必须改变它以匹配空数组。
$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);