在单元测试中使用Laravel辅助函数

15

我正在测试一个使用帮助函数的类。我正在测试的函数如下:

public function upload(UploadedFile $file)
{
    $file = $file->move(base_path() . '/temp');
    $file = new FileSystemPicture($file);

    return $file;
}

当我运行测试并碰到这个帮助函数时,它会提示:

PHP Fatal error:  Call to a member function make() on a non-object

我已经追踪到辅助函数的代码如下:

function base_path($path = '')
{
    return app()->make('path.base').($path ? '/'.$path : $path);
}

我知道我之所以会出现错误,是因为“app”尚未创建,因为我只是测试了我的类,而不是整个应用程序。是否有其他有效的方法来获取我的项目的根目录,或者是否有一种方法可以强制加载“app”,以便它可以在此函数中使用?

3个回答

18

我遇到了这个问题,解决方法是确保:

  1. 我的测试类继承了TestCase。
  2. 如果我的测试类有一个setUp()方法,它调用了parent::setUp()

之后,app_path()和类似的函数就可以正常工作了。


1
这对于集成测试来说没问题,但是对于单元测试,你需要一种模拟辅助函数的方法。 - Rob_vH
1
在调用任何辅助方法之前,应该先调用parent::setUp() - haakym
3
明确一点,测试类应该扩展Tests\TestCase,而不是PHPUnit\Framework\TestCase - murribu

1

有一种方法可以在完全隔离于Laravel环境的情况下模拟使用app()函数的帮助函数。考虑到您的包依赖于illuminate/support,您可以这样做:

<?php

    class Test extends PHPUnit_Framework_TestCase
    {
        protected function mockApplication(array $methods = [])
        {
            return $this->getMock('Illuminate\Foundation\Application', $methods);
        }

        public function testHelperFunction()
        {
            $appMock = $this->mockApplication(['make']);

            \Illuminate\Support\Facades\Facade::setFacadeApplication($appMock);

            $testPath = "my/path";
            $myPath = "otherPath";

            $expectedValue = "{$testPath}/{$myPath}";

            $appMock->expects($this->once())
                    ->method('make')->with('path.base')
                    ->will($this->returnCallback(function () use ($testPath) {
                        return $testPath;
                    }));

            $this->assertSame($expectedValue, base_path($myPath));
        }

    }

0

我刚遇到了这个问题,我的解决方案是将整个 helpers.php 内容包装起来

if (!file_exists('newFunction')) {

这应该可以防止在第一个测试用例执行后尝试重新声明函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接