Laravel控制器测试中的Mockery误报

时间:2015-08-03 21:15:20

标签: phpunit laravel-5 tdd mockery

我正在尝试学习如何在Laravel 5中使用Mockery。我的工作主要基于Way的书(Laravel Testing Decoded)和其他教程,这些教程表示与PHPUnit的集成]只需要tearDown()方法。所以我已经把它包括在内了。问题是它似乎没有在测试之间重置东西。我的测试类内容看起来基本上是这样的:

public function __construct()
{
    $this->mock = Mockery::mock('Class\To\Mock');
}

public function tearDown()
{
    Mockery::close();
}

public function test_RedirectWithoutAuthentication()
{
    // Act
    $this->call('GET', '/path/1');

    // Assert
    $this->assertRedirectedTo('/auth/login');
}

public function test_X()
{
    // Arrange
    $this->mock->shouldReceive('MockedClassMethod')->once();

    // Act
    $this->call('GET', '/path/1');
}

第一个测试工作,Auth中间件将用户踢到登录页面。为了TDD的利益,我在实际编写MockedClassMethod之前编写了第二个测试。所以对我的思维方式来说,它应该是非常失败的。但它并没有。它过去了!

如果我改变测试的顺序,那么"工作" (不成文失败,auth通过)这让我相信它并不是一个真正的订单问题,而是与一个测试没有在下一个测试之前得到清理有关。

任何见解都可以避免我的剩余头发被拉出来。 : - )

2 个答案:

答案 0 :(得分:2)

PHPUnit doc

一致
  

每个测试运行一次setUp()tearDown()模板方法   测试用例类的方法(以及新实例)。

第一次调用构造函数,因此在执行类的第二次测试之前调用tearDown,结果是mockry实例已关闭。

为了解决您的问题,您可以使用setup方法初始化模拟对象。因此,使用以下设置方法替换测试类的类构造函数:

尝试使用它:

protected function setUp() 
{
    $this->mock = Mockery::mock('Class\To\Mock');
}

而不是:

public function __construct()
{
    $this->mock = Mockery::mock('Class\To\Mock');
}

希望这个帮助

答案 1 :(得分:2)

我曾尝试使用Matteo所描述的setUp()方法,它导致测试根本不运行。所以我放弃了那条路,以为我离开了。但是Matteo的建议让我回到了原点。

稍微深入研究为什么导致测试失败,表明$ app对象永远不会被创建。嗯......那么我突然意识到setUp()方法是覆盖一些重要的东西。所以要修复它,所需要的只是先调用父方法!像这样:

public function setUp()
{
    parent::setUp();
    $this->mock = Mockery::mock('Class\To\Mock');
}

从那时起,setUp()和tearDown()按预期工作。

我仍然不确定为什么我似乎找到的所有示例都显示了在构造函数中创建的模拟。也许我还没有得到什么,但至少它现在正在工作...... : - )