使用模拟的 Symfony 单元测试服务找不到 class 名称
Symfony Unit testing Service with mocks doesn't find the class name
我尝试对我的 Symfony 服务(位于 src/AppBundle/Services/CapthaServiceAdapter
)进行纯单元测试:
namespace AppBundle\Services;
use AppBundle\Interfaces\CapthaBuilderInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Gregwar\Captcha\CaptchaBuilder;
/**
* The following class is an adapter for Gregwar Captcha Builder
* I do not set Gregwar's Captha Builder as a Service
* Because I want to stay hidden fromt he service container.
*/
class CapthaServiceAdapter implements CapthaBuilderInterface
{
const IMAGE_INLINE=0;
const IMAGE_NORMAL=1;
/**
* @var Session;
*/
private $session=null;
/**
* @var CaptchaBuilder
*/
private $capthaBuilder=null;
public function __construct(Session $sessionManager)
{
$this->session=$sessionManager;
$this->capthaBuilder=new CaptchaBuilder();
}
/**
* @inheritdoc
* @throws \InvalidArgumentException when type is not either self::IMAGE_INLINE or self::IMAGE_NORMAL
*/
public function build($identifier,$type)
{
if($type!==self::IMAGE_INLINE || $type!==IMAGE_NORMAL){
throw new \InvalidArgumentException("Type should be either CapthaService::IMAGE_INLINE or CapthaService::IMAGE_NORMAL you provided the value: ".$type);
}
$this->builder->build();
$this->session->set($sessionKey,$this->builder->getPhrase());
if($type==self::IMAGE_INLINE){
return $this->builder->inline();
}
return $this->builder->output();
}
/**
* @inheritdoc
*/
public function verify($identifier,$value)
{
$capthaSessionValue=$session->get($identifier);
return $capthaSessionValue && $value===$capthaSessionValue;
}
}
所以我做了以下测试用例(位于tests/AppBundle/Services/CapthcaServiceTest.php
):
namespace Tests\AppBundle\Services;
use PHPUnit\Framework\TestCase;
use AppBundle\Services\CapthaServiceAdapter;
use Symfony\Component\HttpFoundation\Session\Session;
class CapthcaServiceTest extends TestCase
{
private function getServiceForBuild()
{
$mock=$this->createMock(Session::class);
return new CapthaServiceAdapter($mock);
}
public function testBuildInline()
{
$service=$this->getServiceForBuild();
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
$this->assertRegExp('/^data:image\/jpeg;base64,(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)$/i',$element);
}
}
但是当我尝试 运行 时,出现以下错误:
Error: Class 'AppBundle\Services\CapthaServiceAdapter' not found
那么我如何进行测试以查找我的 class?
另外我的pgpunit.xml
包含以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_CLASS" value="AppKernel" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
<exclude>./tests/Appbundle/Controller/DefaultControllerTest.php</exclude>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
编辑 1
通过进行评论中提到的更改(更新了上面的代码)我得到了错误:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
你知道我该如何解决这个问题吗?
编辑 2:
我也看过这个 answer 所以我 post 我的 composer.json
也看到了:
{
"name": "pcmagas/ellakcy_member_app",
"license": "AGPL-v3",
"type": "project",
"autoload": {
"psr-4": {
"AppBundle\": "src/AppBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
"require": {
"php": ">=5.5.9",
"captcha-com/symfony-captcha-bundle": "4.*",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/orm": "^2.5",
"dunglas/angular-csrf-bundle": "^1.1",
"gregwar/captcha": "^1.1",
"sensio/distribution-bundle": "^5.0.19",
"sensio/framework-extra-bundle": "^5.0.0",
"symfony/dom-crawler": "^4.1",
"symfony/monolog-bundle": "^3.1.0",
"symfony/polyfill-apcu": "^1.0",
"symfony/swiftmailer-bundle": "^2.6.4",
"symfony/symfony": "3.4.*",
"symfony/templating": "^3.4",
"symfony/twig-bundle": "^4.1",
"twig/twig": "^1.0||^2.0"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0",
"felixfbecker/language-server": "^5.4",
"jetbrains/phpstorm-stubs": "dev-master",
"phpunit/phpunit": "^6.5",
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "^4.1"
},
"scripts": {
"symfony-scripts": [
"Incenteev\ParameterHandler\ScriptHandler::buildParameters",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installAssets",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installRequirementsFile",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::prepareDeploymentTarget"
],
"post-install-cmd": [
"@symfony-scripts"
],
"post-update-cmd": [
"@symfony-scripts"
]
},
"config": {
"sort-packages": true
},
"extra": {
"symfony-app-dir": "app",
"symfony-bin-dir": "bin",
"symfony-var-dir": "var",
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"branch-alias": null
}
}
如您所见,它也具有自动加载功能 class:
"autoload": {
"psr-4": {
"AppBundle\": "src/AppBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
也可以改成这样:
"autoload": {
"psr-4": {
"AppBundle\": "src/AppBundle",
"AppBundle\Services":"src/AppBundle/Services",
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
导致此错误:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
我可以让 phphunit 查看适当的命名空间吗?
在你的代码中有一行提到:
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
classCapthaService
是在哪里定义的?您的意思是 CapthaServiceAdapter
(可能是重构后遗留下来的?)
换成那个应该没问题
我尝试对我的 Symfony 服务(位于 src/AppBundle/Services/CapthaServiceAdapter
)进行纯单元测试:
namespace AppBundle\Services;
use AppBundle\Interfaces\CapthaBuilderInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Gregwar\Captcha\CaptchaBuilder;
/**
* The following class is an adapter for Gregwar Captcha Builder
* I do not set Gregwar's Captha Builder as a Service
* Because I want to stay hidden fromt he service container.
*/
class CapthaServiceAdapter implements CapthaBuilderInterface
{
const IMAGE_INLINE=0;
const IMAGE_NORMAL=1;
/**
* @var Session;
*/
private $session=null;
/**
* @var CaptchaBuilder
*/
private $capthaBuilder=null;
public function __construct(Session $sessionManager)
{
$this->session=$sessionManager;
$this->capthaBuilder=new CaptchaBuilder();
}
/**
* @inheritdoc
* @throws \InvalidArgumentException when type is not either self::IMAGE_INLINE or self::IMAGE_NORMAL
*/
public function build($identifier,$type)
{
if($type!==self::IMAGE_INLINE || $type!==IMAGE_NORMAL){
throw new \InvalidArgumentException("Type should be either CapthaService::IMAGE_INLINE or CapthaService::IMAGE_NORMAL you provided the value: ".$type);
}
$this->builder->build();
$this->session->set($sessionKey,$this->builder->getPhrase());
if($type==self::IMAGE_INLINE){
return $this->builder->inline();
}
return $this->builder->output();
}
/**
* @inheritdoc
*/
public function verify($identifier,$value)
{
$capthaSessionValue=$session->get($identifier);
return $capthaSessionValue && $value===$capthaSessionValue;
}
}
所以我做了以下测试用例(位于tests/AppBundle/Services/CapthcaServiceTest.php
):
namespace Tests\AppBundle\Services;
use PHPUnit\Framework\TestCase;
use AppBundle\Services\CapthaServiceAdapter;
use Symfony\Component\HttpFoundation\Session\Session;
class CapthcaServiceTest extends TestCase
{
private function getServiceForBuild()
{
$mock=$this->createMock(Session::class);
return new CapthaServiceAdapter($mock);
}
public function testBuildInline()
{
$service=$this->getServiceForBuild();
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
$this->assertRegExp('/^data:image\/jpeg;base64,(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)$/i',$element);
}
}
但是当我尝试 运行 时,出现以下错误:
Error: Class 'AppBundle\Services\CapthaServiceAdapter' not found
那么我如何进行测试以查找我的 class?
另外我的pgpunit.xml
包含以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_CLASS" value="AppKernel" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
<exclude>./tests/Appbundle/Controller/DefaultControllerTest.php</exclude>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
编辑 1
通过进行评论中提到的更改(更新了上面的代码)我得到了错误:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
你知道我该如何解决这个问题吗?
编辑 2:
我也看过这个 answer 所以我 post 我的 composer.json
也看到了:
{
"name": "pcmagas/ellakcy_member_app",
"license": "AGPL-v3",
"type": "project",
"autoload": {
"psr-4": {
"AppBundle\": "src/AppBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
"require": {
"php": ">=5.5.9",
"captcha-com/symfony-captcha-bundle": "4.*",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/orm": "^2.5",
"dunglas/angular-csrf-bundle": "^1.1",
"gregwar/captcha": "^1.1",
"sensio/distribution-bundle": "^5.0.19",
"sensio/framework-extra-bundle": "^5.0.0",
"symfony/dom-crawler": "^4.1",
"symfony/monolog-bundle": "^3.1.0",
"symfony/polyfill-apcu": "^1.0",
"symfony/swiftmailer-bundle": "^2.6.4",
"symfony/symfony": "3.4.*",
"symfony/templating": "^3.4",
"symfony/twig-bundle": "^4.1",
"twig/twig": "^1.0||^2.0"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0",
"felixfbecker/language-server": "^5.4",
"jetbrains/phpstorm-stubs": "dev-master",
"phpunit/phpunit": "^6.5",
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "^4.1"
},
"scripts": {
"symfony-scripts": [
"Incenteev\ParameterHandler\ScriptHandler::buildParameters",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::buildBootstrap",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installAssets",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::installRequirementsFile",
"Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::prepareDeploymentTarget"
],
"post-install-cmd": [
"@symfony-scripts"
],
"post-update-cmd": [
"@symfony-scripts"
]
},
"config": {
"sort-packages": true
},
"extra": {
"symfony-app-dir": "app",
"symfony-bin-dir": "bin",
"symfony-var-dir": "var",
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"branch-alias": null
}
}
如您所见,它也具有自动加载功能 class:
"autoload": {
"psr-4": {
"AppBundle\": "src/AppBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
也可以改成这样:
"autoload": {
"psr-4": {
"AppBundle\": "src/AppBundle",
"AppBundle\Services":"src/AppBundle/Services",
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
导致此错误:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
我可以让 phphunit 查看适当的命名空间吗?
在你的代码中有一行提到:
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
classCapthaService
是在哪里定义的?您的意思是 CapthaServiceAdapter
(可能是重构后遗留下来的?)
换成那个应该没问题