Phpunit Laravel控制器测试中的模拟假阳性

Phpunit Laravel控制器测试中的模拟假阳性,phpunit,laravel-5,tdd,mockery,Phpunit,Laravel 5,Tdd,Mockery,我正在尝试学习如何使用拉威尔5的嘲弄。我的工作主要基于Way的书Laravel Testing Decoded和其他教程,其中说[与PHPUnit]的集成只需要拆卸方法。所以我把它包括在内了。问题是,它似乎没有在测试之间重置东西。我的测试类内容基本上如下所示: public function __construct() { $this->mock = Mockery::mock('Class\To\Mock'); } public function tearDown() {

我正在尝试学习如何使用拉威尔5的嘲弄。我的工作主要基于Way的书Laravel Testing Decoded和其他教程,其中说[与PHPUnit]的集成只需要拆卸方法。所以我把它包括在内了。问题是,它似乎没有在测试之间重置东西。我的测试类内容基本上如下所示:

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实际编写之前编写了第二个测试。所以在我看来,它应该失败得惊人。但事实并非如此。它过去了

如果我改变测试的顺序,它会工作——不成文的失败,认证通过——这让我相信这不是真正的顺序问题,而是与一个测试没有在下一个测试之前得到清理有关

任何洞察都会使我剩下的头发不至于被拔掉-

与以下内容一致:

每个测试运行一次setUp和tearDown模板方法 方法和测试用例类的新实例

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

为了解决您的问题,您可以使用init模拟对象的setup方法。因此,用setup方法替换测试类的类构造函数,如下所示:

尝试使用以下方法:

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

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

希望此帮助

我曾尝试使用Matteo描述的设置方法,但它导致测试根本无法运行。所以我放弃了那门课,以为我已经走远了。但马特奥的建议让我又回到了这一点上

稍微深入探究一下它导致测试失败的原因,就会发现$app对象从未被创建过。隐马尔可夫模型。。。所以我突然意识到设置方法覆盖了一些重要的东西。所以要修复它,只需首先调用父方法!像这样:

public function setUp()
{
    parent::setUp();
    $this->mock = Mockery::mock('Class\To\Mock');
}
从那时起,安装和拆卸工作就如预期的那样


我仍然不确定为什么我找到的所有示例都显示在构造函数中创建了mock。也许我还是没有得到什么,但至少它起作用了。。。目前:-

您是否尝试过将mockry mock定义放在setup方法中而不是构造函数中?是否可以尝试用受保护的函数setup替换公共函数\uuu构造?您好,Jared of couse!我不知道您的测试类有一个层次结构,其中包含一个已经实现的安装方法。很高兴这工作很好!祝你好运非常感谢。如果没有你的建议,我可能会花很长时间才回到设置中。你整天都在做的事情之一,就在你面前……嗨@jared,欢迎你!如果你认为我的回答有用,请考虑我的回答。