试图在测试中模拟学说存储库,与 findOneby 方法一起使用时,returnValueMap((总是返回null。p>我嘲笑了两个实体,然后尝试使用给定的返回值映射嘲笑其存储库。测试失败和调试表明returnValueMap((正在返回null。
这是要测试的类(否定器(
<?php
declare(strict_types=1);
namespace AppSerializer;
use AppEntityAdditionalService;
use AppRepositoryAdditionalServiceRepository;
use DtoAdditionalServiceCollection;
use SymfonyComponentSerializerNormalizerDenormalizerInterface;
class AdditionalServiceCollectionDenormalizer implements DenormalizerInterface
{
/** @var AdditionalServiceRepository */
private $additionalServiceRepository;
public function __construct(AdditionalServiceRepository $additionalServiceRepository)
{
$this->additionalServiceRepository = $additionalServiceRepository;
}
public function denormalize($mappedCsvRow, $class, $format = null, array $context = [])
{
$addtionalServicesCollection = new AdditionalServiceCollection();
foreach ($mappedCsvRow as $fieldName => $fieldValue) {
/** @var AdditionalService $additionalService */
$additionalService = $this->additionalServiceRepository->findOneBy(['name'=>$fieldName]);
if ($additionalService) {
$addtionalServicesCollection->add($additionalService->getId(), $fieldValue);
}
}
return $addtionalServicesCollection;
}
public function supportsDenormalization($data, $type, $format = null)
{
return $type instanceof AdditionalServiceCollection;
}
}
这是我的测试课:
<?php
namespace AppTestsImportConfig;
use AppEntityAdditionalService;
use AppRepositoryAdditionalServiceRepository;
use AppSerializerAdditionalServiceCollectionDenormalizer;
use PHPUnitFrameworkTestCase;
use DtoAdditionalServiceCollection;
class AddionalServiceCollectionDenormalizerTest extends TestCase
{
public function provider()
{
$expected = new AdditionalServiceCollection();
$expected->add(1, 22.1)->add(2, 3.1);
return [
[['man_1' => 22.1], $expected],
[['recycling' => 3.1], $expected],
];
}
/**
* @dataProvider provider
* @covers AppSerializerAdditionalServiceCollectionDenormalizer::denormalize
*/
public function testDenormalize(array $row, AdditionalServiceCollection $exptected)
{
$manOneService = $this->createMock(AdditionalService::class);
$manOneService->expects($this->any())->method('getId')->willReturn(1);
$recycling = $this->createMock(AdditionalService::class);
$recycling->expects($this->any())->method('getId')->willReturn(2);
$additionalServicesRepoMock = $this
->getMockBuilder(AdditionalServiceRepository::class)
->setMethods(['findOneBy'])
->disableOriginalConstructor()
->getMock();
$additionalServicesRepoMock
->expects($this->any())
->method('findOneBy')
->will($this->returnValueMap(
[
['name'=>['man_1'], $manOneService],
['name'=>['recycling'], $recycling],
]
));
$denormalizer = new AdditionalServiceCollectionDenormalizer($additionalServicesRepoMock);
self::assertEquals($exptected, $denormalizer->denormalize($row, AdditionalServiceCollection::class));
}
}
我很难调试phpunit库,最终确定是findOneby((方法期望两个参数,其中第二个参数是可选的(设置为null(
willreturnmap((方法如下:
/**
* Stubs a method by returning a value from a map.
*/
class ReturnValueMap implements Stub
{
/**
* @var array
*/
private $valueMap;
public function __construct(array $valueMap)
{
$this->valueMap = $valueMap;
}
public function invoke(Invocation $invocation)
{
$parameterCount = count($invocation->getParameters());
foreach ($this->valueMap as $map) {
if (!is_array($map) || $parameterCount !== (count($map) - 1)) {
continue;
}
$return = array_pop($map);
if ($invocation->getParameters() === $map) {
return $return;
}
}
return;
}
我怀疑该方法始终是由于未满足的条件$parameterCount !== (count($map) - 1)
而返回的。一个断点证实了我的疑问,还揭示了$invocation->getParameters()
转储如下:
array(2) {
[0] =>
array(1) {
'name' =>
string(5) "man_1"
}
[1] =>
NULL
}
因此,我必须明确将null
作为第二个参数。最后,工作地图必须为:
$this->additionalServicesRepoMock
->method('findOneBy')
->willReturnMap([
[['name' => 'man_1'], null, $manOneService],
[['name' => 'recycling'], null, $recyclingService],
]);
它看起来像testDenormalize()
中returnValueMap()
的参数需要括号以使其索引阵列。
这是phpunit文档中代码段的稍微修改的版本:
<?php
namespace AppTests;
use PHPUnitFrameworkTestCase;
class ReturnValueMapTest extends TestCase
{
public function testReturnValueMapWithAssociativeArray()
{
$stub = $this->createMock(SomeClass::class);
$map = [
[
'name' => ['man_1'],
'Hello'
],
];
$stub->method('doSomething')
->will($this->returnValueMap($map));
// This will fail as doSomething() returns null
$this->assertSame('Hello', $stub->doSomething(['name' => ['man_1']]));
}
public function testReturnValueMapWithIndexedArray()
{
$stub = $this->createMock(SomeClass::class);
$map = [
[
['name' => ['man_1']], // Notice the difference
'Hello'
],
];
$stub->method('doSomething')
->will($this->returnValueMap($map));
$this->assertSame('Hello', $stub->doSomething(['name' => ['man_1']]));
}
}
class SomeClass
{
public function doSomething()
{}
}