Symfony Unit testing Service with mocks doesn't find the class name - php

I try to test on a pure unit test my Symfony Service (located in 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;
}
}
So I did the following Test case (located in 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);
}
}
But when I try to run it I get the following error:
Error: Class 'AppBundle\Services\CapthaServiceAdapter' not found
So how I can make my test to look for my class?
Also my pgpunit.xml contains the following content:
<?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>
Edit 1
By doing changes mentioned in the comments (updated the code above) I get the error:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
Do you know how I can fix that?
Edit 2:
I also have seen this answer so I post my composer.json as well:
{
"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
}
}
As you can see it has the autoloading class as well:
"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"
]
},
Also By changing into this:
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle",
"AppBundle\\Services":"src/AppBundle/Services",
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
Results into this error:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
Hos I can make the phphunit to look into the appropriate namespace?

Over your code there is a line that mentions:
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
The class CapthaService where is defined? Did you mean CapthaServiceAdapter (perhaps leftover from a refactor?)
Change into that and that should be fine.

Related

Interface "Composer\Plugin\PluginInterface" not found

I am writing composer package and in my plugin code I am trying to get Composer\Plugin\PluginInterface but I'm receiving Interface "Composer\Plugin\PluginInterface" not found when I install my package.
My plugin composer.json
{
"name": "..../.....",
"description": "....",
"keywords": [
//...
],
"license": "MIT",
"authors": [
{
"name": "...",
"email": "...",
"homepage": "...",
}
],
"type": "composer-plugin",
"require": {
"php": ">=8.0",
"composer-plugin-api": "~2.0", <-- here
},
"autoload": {
"psr-4": {
"...\\....\\": "src/"
}
},
"extra": {
"class": "...\\....\\....",
"laravel": {
"providers": [
"...\\....\\...."
]
}
}
}
And here is my plugin structure: (In case I forget to add something!)
<?php
namespace ...\....;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface; <-- Not Found!
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
class MyClassPlugin implements PluginInterface, EventSubscriberInterface
{
public static function getSubscribedEvents(){}
public static function update(){...}
public static function myFunctionOne(){...}
public static function myFunctionTwo(){...}
public static function myFunctionThree(){...}
public static function generateConfig(){...}
public static function activate(){...}
public static function deactivate(){...}
public static function uninstall(){...}
}
Also this is my installed composer: Composer version 2.3.5
Any idea?

laravel 4.1.28 command registration is not working

I am currently working with Laravel version 4.1.28 and have created a command with php artisan command:make which works fine and created a file under app/commands/ArchiveMailorder.php:
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class ArchiveMailorder extends Command {
protected $name = 'archive:mailorder';
protected $description = 'This is my first command';
public function __construct()
{
parent::__construct();
}
public function fire()
{
$this->line("Hello world");
}
protected function getArguments()
{
return array(
array(),
);
}
protected function getOptions()
{
return array(
array(),
);
}
}
Now when I try to register this command inside app/start/artisan.php like:
Artisan::add(new ArchiveMailorder());
Or
\Illuminate\Foundation\Artisan::add(new ArchiveMailorder());
Or
\Illuminate\Support\Facades\Artisan::add(new ArchiveMailorder());
I get the following error:
{"error":{"type":"ErrorException","message":"Missing argument 1 for Symfony\\Component\\Console\\Command\\Command::addArgument()","file":"C:\\xampp\\htdocs\\mocs\\vendor\\symfony\\console\\Symfony\\Component\\Console\\Command\\Command.php","line":362}}
I have followed these links for creating and registering a command:
Cron Job with Laravel 4
https://laravel.com/docs/4.2/commands#building-a-command
But still can not make the command work. So please tell me what am I doing wrong? And what shall I do to fix this problem?
Oh, and comoser.json file looks like this:
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"laravel/framework": "4.1.*",
"mews/purifier": "dev-master",
"anahkiasen/former": "dev-master",
"laracasts/utilities": "1.0"
},
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
},
"scripts": {
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-update-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-create-project-cmd": [
"php artisan key:generate"
]
},
"config": {
"preferred-install": "dist"
},
"minimum-stability": "stable"
}
In laravel 4.1/4.2 you register command simple just by adding
Artisan::add(new SomeCommandName());
In your command your issue lies with this function:
protected function getArguments()
{
return array(
array(),
);
}
Remove that function unless you're supplying arguments. Since you're returning an array.
Unless you need any of these functions, you'll just need these two functions to get you started, consult the laravel docs for anything else I guess? :
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function fire()
{
// Do stuff
}

Silex web test fails

I'm trying to write a simple web test to test my silex api using phpunit but
I keep getting this error when i try to run it..
1) App\Tests\BlogControllerTest::testInitialPage
TypeError: Argument 1 passed to Symfony\Component\HttpKernel\Client::__construct() must implement interface Symfony\Component\HttpKernel\HttpKernelInterface, null given, called in C:\vendor\silex\silex\src\Silex\WebTestCase.php on line 63
This is my web test
<?php
namespace App\Tests;
use Silex\WebTestCase;
class BlogControllerTest extends WebTestCase
{
public function createApplication()
{
require dirname(dirname(__DIR__)) . '/src/Application.php';
}
public function testInitialPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/Blog/1');
$this->assertTrue($client->getResponse()->isOk());
}
}
The content of my Composer file:
{
"require": {
"silex/silex": "~2.0",
"symfony/validator": "^4.0",
"crell/api-problem": "~1.7",
"tobiassjosten/responsible-service-provider": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "6",
"symfony/browser-kit": "^4.0",
"symfony/css-selector": "^4.0"
},
"autoload": {
"psr-4": {
"App\\": "src/",
"Tests\\": "tests/"
}
}
}
From documentation:
For your WebTestCase, you will have to implement a createApplication method, which returns your application instance:
public function createApplication()
{
// app.php must return an Application instance
return require __DIR__.'/path/to/app.php';
}
So here's what you need:
public function createApplication()
{
return new Application();
}
But in the most cases it would be better to return configured application, from your bootstrap (bootstrap example):
public function createApplication()
{
require __DIR__.'../web/index-test.php'; // path to your bootstrap file
return $app;
}

Slim3 PSR-4 autoloader

I am writing Slim3 API, for some reason slim is not loading namespace defined in composer.
Here is the project structure.
FolderStruc:
projectApi
- composer.json
- src
- public
- index.php
- ProjectName
- Api
- Controllers
- Entities
- Commands
My composer file packages and PSR-4 autoloader settings.
composer.json
{
"require": {
"slim/slim": "^3.0",
"symfony/yaml": "3.1",
"symfony/console": "3.1",
"symfony/process": "3.1",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"sabre/xml": "1.1.0",
"php-di/php-di": "#dev",
"php-amqplib/php-amqplib": "#dev",
"ramsey/uuid": "dev-master",
"monolog/monolog": "~1.15#dev",
"predis/predis": "~1.0.1",
"spipu/html2pdf": "^4.5",
"iio/libmergepdf": "~3.0"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"src\\ProjectName\\": "src/ProjectName/"
}
},
"autoload-dev": {
"psr-4": { "src\\ProjectName\\Tests\\": "tests" }
}
}
index.php
CategoryController
namespace ProjectName\Api\Controllers;
class CategoryController
{
/**
* #param \Slim\App $app
* #return array
*/
public function index(\Slim\App $app)
{
return ['Cats', 'Cats2', 'Cats3'];
}
}
** routes.php **
$app->get('/v1/category/list', function (Request $request, Response $response) {
$response = $response->withHeader('Content-type', 'application/json');
$categoryCtrl = new \ProjectName\Api\Controllers\CategoryController();
});
Slim fails to load namespace \ProjectName\Api\Controllers\CategoryController
any idea where and what is going wrong?
Best Regards
Danyal
You have incorrect autoloader definitions in your composer.json file.
The pattern is:
"psr-4": {
"Namespace\\Prefix\\": "/path/to/source/root"
}
So in your case it probably should be:
"autoload": {
"psr-4": {
"ProjectName\\": "src/ProjectName/"
}
},
"autoload-dev": {
"psr-4": { "ProjectName\\Tests\\": "tests/" }
}
autoload-dev definition is assuming there's a tests directory under project root path, which is not mentioned in your question.

Composer - unable to autoload files

I have a simple composer project on GitHub with the directory structure as:
/--
-composer.json
-lib/ComposerTest.php
with the ComposerTest.php file as:
namespace lib;
class ComposerTest{
public function doTest(){
return "This class was loaded from Composer\n";
}
}
and composer.json as:
{
"name":"sc/composerTest",
"autoload":{
"psr-0":{
"lib":"./"
}
}
}
Using the following composer.json file, I'm able to include the GitHub project into my vendor folder, but cannot get it to autoload.
{
"description" : "The CodeIgniter Application with Composer",
"require": {
"php": ">=5.3.2",
"codeigniter/framework": "3.1.*",
"kriswallsmith/buzz":"*",
"maltyxx/bower": "^1.0",
"sc/composerTest":"dev-master"
},
"require-dev": {
"mikey179/vfsStream": "1.1.*"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/sc/composerTest.git"
}
]
}
Can someone advise?
Edit: ComposerTest Controller
class ComposerTest extends CI_Controller
{
public function index()
{
$composerTest = new ComposerTest();
echo $composerTest->doTest();
}
}

Categories