测试将上传文件附加到表单提交与 PhpSpec


Testing attaching UploadedFile to form submit with PhpSpec

我正在尝试测试一个图像导入器,该程序获取文件并提交附加了该图像的表单。测试的那部分似乎是它失败的部分,我不确定如何解决它。

我理解不"嘲笑你不拥有的东西"的概念,但是如果不承认对私有方法的调用,insertImageThroughForm测试不起作用。

我收到以下错误:

75  ! imports image assets
        method call:
          - submit(["file" => ["assetFile" => ["file" => Symfony'Component'HttpFoundation'File'UploadedFile:0000000027d380bc00007f8c6cad27ec Object (
            'test' => false
            'originalName' => 'picco.jpg'
            'mimeType' => 'application/octet-stream'
            'size' => null
            'error' => 0
        )]]], false)
        on Double'Symfony'Component'Form'Form'P22 was not expected, expected calls were:
          - submit(exact(["file" => ["assetFile" => ["file" => Double'Symfony'Component'Finder'SplFileInfo'P19:0000000027d3807500007f8c6cad27ec Object (
            'objectProphecy' => Prophecy'Prophecy'ObjectProphecy Object (*Prophecy*)
            'relativePath' => null
            'relativePathname' => null
        )]]]), exact(false))
          - submit(exact(["file" => ["assetFile" => ["file" => Double'Symfony'Component'Finder'SplFileInfo'P20:0000000027d3803000007f8c6cad27ec Object (
            'objectProphecy' => Prophecy'Prophecy'ObjectProphecy Object (*Prophecy*)
            'relativePath' => null
            'relativePathname' => null
        )]]]), exact(false))

ImageImporterSpec.php

const TEMP_PATH = '/tmp/crmpicco/imageImporter';
function it_imports_image_assets(
    Category $category,
    AssetFactory $assetFactory,
    Asset $asset,
    Finder $finder,
    SplFileInfo $file1,
    SplFileInfo $file2,
    FormFactory $formFactory,
    Form $form
) {
  $category->getId()->willReturn(14);
  $createTempPathFilesystem = new Filesystem();
  $createTempPathFilesystem->mkdir(self::TEMP_PATH);
  $createTempPathFilesystem->mkdir(self::TEMP_PATH . DIRECTORY_SEPARATOR . 'courses');
  $imageImportPath = self::TEMP_PATH . DIRECTORY_SEPARATOR . 'courses/';
  $createTempPathFilesystem->touch($imageImportPath . 'picco.jpg');
  $createTempPathFilesystem->touch($imageImportPath . 'morton.jpg');
  $finder->files()->willReturn($finder);
  $finder->in($imageImportPath)->willReturn($finder);
  $finder->getIterator()->willReturn(new 'ArrayIterator([
      $file1->getWrappedObject(),
      $file2->getWrappedObject(),
  ]));
  $file1->getPathname()->willReturn($imageImportPath . 'picco.jpg');
  $file2->getPathname()->willReturn($imageImportPath . 'morton.jpg');
  $assetFactory->createForCategory(14)->willReturn($asset);
  $formFactory->create('category_asset', $asset, ['csrf_protection' => false])->willReturn($form);
  $form->submit(['file' => ['assetFile' => ['file' => $file1->getWrappedObject()]]], false)->shouldBeCalled();
  $form->submit(['file' => ['assetFile' => ['file' => $file2->getWrappedObject()]]], false)->shouldBeCalled();
  $this->importImageAssets('courses/', $category)->shouldBeCalled();
}

ImageImporter.php

public function importImageAssets($importDirectory, Category $category)
{
    $finder = new Finder();
    $finder->files()->in($importDirectory);
    if (count($finder) > 0) {
        foreach ($finder as $image) {
            $filename = $image->getBasename('.' . $image->getExtension());
            $filepath = $importDirectory . '/' . $image->getFilename();
            $asset = $this->assetFactory->createForCategory($category->getId());
            $asset->setName($filename);
            $this->insertImageThroughForm($asset, $filepath);
            $this->entityManager->persist($asset);
        }
        $this->entityManager->flush();
    }
}
 private function insertImageThroughForm(Asset $asset, $filePath)
 {
  $form = $this->formFactory->create('category_asset', $asset, ['csrf_protection' => false]);
  $uploadedFile = new UploadedFile($filePath, basename($filePath));
  $form->submit(['file' => ['assetFile' => ['file' => $uploadedFile]]], false);
}

您正在测试的与其说是单元测试,不如说是集成测试。PhpSpec 不适合集成测试,而仅适用于低单元测试。为什么是集成测试?因为您使用的是真正的文件系统,它是外部服务,也很少有第三方库,如FilesystemFinder

您正在尝试模拟FinderFinder直接在方法中初始化,因此无法模拟。您需要将Finder作为类的依赖项注入。