测试将UploadedFile附加到表单提交时使用PhpSpec

时间:2016-03-04 13:34:34

标签: php symfony testing tdd 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);
}

1 个答案:

答案 0 :(得分:4)

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

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