Php 如何在symfony2中测试服务?
由于我在使用服务,这个问题可能最终成为symfony中依赖注入的一个问题。目前,我正试图通过phpunit测试来测试我的服务中的一个简单功能,但我不断收到以下错误:Php 如何在symfony2中测试服务?,php,web-services,symfony,dependency-injection,Php,Web Services,Symfony,Dependency Injection,由于我在使用服务,这个问题可能最终成为symfony中依赖注入的一个问题。目前,我正试图通过phpunit测试来测试我的服务中的一个简单功能,但我不断收到以下错误: PHP Catchable fatal error: Argument 1 passed to Caremonk\MainSiteBundle\Tests\Services\GeoTest::__construct() must be an instance of Caremonk\MainSiteBundle\Tests\Ser
PHP Catchable fatal error: Argument 1 passed to Caremonk\MainSiteBundle\Tests\Services\GeoTest::__construct() must be an instance of Caremonk\MainSiteBundle\Tests\Services\Geo, none given, called in /usr/share/nginx/html/caremonk/vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php on line 473 and defined in /usr/share/nginx/html/caremonk/src/Caremonk/MainSiteBundle/Tests/Services/GeoTest.php on line 14
从错误中可以明显看出,我正在尝试创建我的服务实例,但没有传递正确的参数,因此下面是我的services.yml文件:
#src/Caremonk/MainSiteBundle/Resources/config/services.yml
parameters:
caremonk_main_site.geo.class: Caremonk\MainSiteBundle\Services\Geo
caremonk_main_site.geo_test.class: Caremonk\MainSiteBundle\Tests\Services\GeoTest
services:
geo:
class: %caremonk_main_site.geo.class%
arguments: []
geo_test:
class: %caremonk_main_site.geo_test.class%
arguments: ["@geo"]
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: "@CaremonkMainSiteBundle/Resources/config/services.yml" }
# Other config.yml stuff
以下是我建立的服务:
<?php
//src/Caremonk/MainSiteBundle/Services/Geo.php
namespace Caremonk\MainSiteBundle\Services;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class Geo extends Controller
{
public $pi80;
public $latRad;
public $lngRad;
public function __construct()
{
$this->pi80 = M_PI / 180;
}
// Takes longitude and latitude and converts them into their respective radians
// We also set our class properties to these values
public function setCoordinates($lat,$lng)
{
$this->latRad = $lat * $this->pi80;
$this->lngRad = $lng * $this->pi80;
}
public function distance($lat2, $lng2, $miles = true)
{
$lat1 = $this->latRad;
$lng1 = $this->lngRad;
$lat2 *= $pi80;
$lng2 *= $pi80;
$r = 6372.797; // mean radius of Earth in km
$dlat = ($lat2 - $lat1)/2;
$dlng = ($lng2 - $lng1)/2;
$a = sin($dlat) * sin($dlat) + cos($lat1) * cos($lat2) * sin($dlng) * sin($dlng);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
return ($miles ? ($km * 0.621371192) : $km);
}
// This function returns the minimum latitude in radians
public function min_lat($lat,$lng,$dis)
{
$dis /= .62137119;
$ratio = $dis/6372.797;
return asin(sin($lat)*cos($ratio) + cos($lat)*sin($ratio)*cos(M_PI));
}
// This function returns the max latitude in radians
public function max_lat($lat,$lng,$dis)
{
$dis /= .62137119;
$ratio = $dis/6372.797;
return asin(sin($lat)*cos($ratio) + cos($lat)*sin($ratio)*cos(0));
}
// This function returns max longitude in radians
public function max_lon($lat,$lng,$dis)
{
$dis /= .62137119;
$ratio = $dis/6372.797;
return $lng + atan2(sin(M_PI/2)*sin($ratio)*cos($lat),cos($ratio)-sin($lat)*sin($lat));
}
// This function returns min longitude in radians
public function min_lon($lat,$lng,$dis)
{
$dis /= .62137119;
$ratio = $dis/6372.797;
return $lng + atan2(sin(M_PI*1.5)*sin($ratio)*cos($lat),cos($ratio)-sin($lat)*sin($lat));
}
}
我不太了解依赖性,我希望我在这篇文章中对它的解释与symfony的想法相近。请让我知道我做错了什么,这样我就可以测试我的服务。在您的测试用例中,您不会在构造函数中得到任何东西-您可以在setupBeforeClass或setup方法中设置要测试的对象,例如
public static function setUpBeforeClass()
{
//start the symfony kernel
$kernel = static::createKernel();
$kernel->boot();
//get the DI container
self::$container = $kernel->getContainer();
//now we can instantiate our service (if you want a fresh one for
//each test method, do this in setUp() instead
self::$geo = self::$container->get('geo');
}
(请注意,您也不需要将测试类设置为服务,因此可以从services.yml中删除geo_测试服务)
一旦您完成了这项工作,您就应该能够使用以下内容运行您的测试用例
cd /root/of/project
phpunit -c app src/Caremonk/MainSiteBundle/Tests/Services/GeoTest.php
如果您不打算测试控制器(使用客户端,因为这样调用的控制器将使用一个新的容器),您的测试类应该只扩展KernelTestCase(Symfony\Bundle\FrameworkBundle\test)。要启动内核并获取服务,您可以在测试设置中执行以下操作:
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class MyTest extends KernelTestCase
{
public function setUp()
{
$kernel = self::bootKernel();
$this->geo = $kernel->getContainer()->get('geo');
}
...
}
更多信息:
注:
setUp
方法,而不是setUpBeforeClass
(就像接受的答案一样)李>
静态::$kernel
(引导后)访问如果您不想在一个应用程序中进行测试,而是在一个独立的捆绑包中进行测试,我建议您看看这个非常详细的答案。完美的解决方案,我只想补充一点,如果您使用symfony 2.4.x,您的测试类必须从WebTestCase扩展,这为我节省了很多时间!谢谢,回答得很好!自从上两天以来一直在寻找这个问题,Symfony 2.6在测试类中添加了“扩展WebTestCase”。(使用Symfony\Bundle\FrameworkBundle\Test\WebTestCase;)我用它来测试翻译句子的结构
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class MyTest extends KernelTestCase
{
public function setUp()
{
$kernel = self::bootKernel();
$this->geo = $kernel->getContainer()->get('geo');
}
...
}