Why console application fails to retrieve mocked service during testing? - php

I have the following console application:
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\Myservice;
class MyCommand extends Command
{
protected $signature = 'test';
public function handle(Myservice $service){
dump($service->dummy());
}
}
And I have the following service:
namespace App\Services;
class Myservice
{
public function dummy()
{
return false;
}
}
I also made the following test:
namespace Tests\Console;
use Illuminate\Foundation\Testing\TestCase;
use Mockery;
class TestMyCommand extends TestCase
{
public function testCommand()
{
$service = Mockery::mock(Myservice::class);
$service->shouldReceive('dummy')->andReturn(true);
app()->bind(MyService::class,$service);
$this->artisan('test')
$service->shouldHaveReceived('dummy')->andReturn(true);
}
}
But I retrieve the following error:
There was 1 error:
1) Tests\Console\TestMyCommand::testCommand
Mockery\Exception\InvalidCountException: Method dummy(<Any Arguments>) from Mockery_0__Tests_Console_MyService should be called
at least 1 times but called 0 times.
/var/www/html/api/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php:47
/var/www/html/api/vendor/mockery/mockery/library/Mockery/Expectation.php:312
/var/www/html/api/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php:46
/var/www/html/api/vendor/mockery/mockery/library/Mockery/VerificationDirector.php:36
/var/www/html/api/tests/Console/MyCommand.php:20
So why I am unable to provide a mocked service to the command?
#Edit 1:
I tried the following:
<?php
namespace Tests\Console;
use Illuminate\Foundation\Testing\TestCase;
use Tests\CreatesApplication;
use Mockery;
class TestMyCommand extends TestCase
{
use CreatesApplication;
public function testCommand()
{
$service = Mockery::mock(Myservice::class);
$service->shouldReceive('dummy')->andReturn(true);
app()->instance(MyService::class,$service);
$this->artisan('test');
$service->shouldHaveReceived('dummy')->andReturn(true);
}
}
And the following:
<?php
namespace Tests\Console;
use Illuminate\Foundation\Testing\TestCase;
use Tests\CreatesApplication;
use Mockery;
class TestMyCommand extends TestCase
{
use CreatesApplication;
public function testCommand()
{
$service = Mockery::mock(Myservice::class);
$service->shouldReceive('dummy')->andReturn(true);
$this->app->instance(MyService::class,$service);
$this->artisan('test');
$service->shouldHaveReceived('dummy')->andReturn(true);
}
}
But still get the error:
Time: 3.32 seconds, Memory: 38.00 MB
There was 1 error:
1) Tests\Console\TestMyCommand::testCommand
Mockery\Exception\InvalidCountException: Method dummy(<Any Arguments>) from Mockery_0__Tests_Console_Myservice should be called
at least 1 times but called 0 times.
/var/www/html/api/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php:47
/var/www/html/api/vendor/mockery/mockery/library/Mockery/Expectation.php:312
/var/www/html/api/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php:46
/var/www/html/api/vendor/mockery/mockery/library/Mockery/VerificationDirector.php:36
/var/www/html/api/tests/Console/TestMyCommand.php:21
ERRORS!
Tests: 1, Assertions: 2, Errors: 1.
Generating code coverage report in HTML format ... done

Related

Why I am unable to assert that method has been called on my mocked service?

I have made a simple class named MyService
namespace App\Services;
class MyService
{
private $anotherService;
public function setService(AnotherService $anotherService)
{
$this->anotherService = $anotherService;
}
public function getService()
{
if(empty($this->anotherService)){
$this->setService(new AnotherService());
}
return $this->anotherService;
}
public function call()
{
$anotherService = $this->getService();
$anotherService->SetXY(5,10);
}
}
As you can se via a setter I set as Depedency the AnotherService:
namespace App\Services;
class AnotherService
{
public function SetXY($x,$y)
{
}
}
In order to test whether the MyService runs as expected I made the following test:
namespace Tests\Services;
namespace Tests\Services;
use App\Services\MyService;
use App\Services\AnotherService;
use PHPUnit\Framework\TestCase;
use Mockery;
class MyServiceTest extends TestCase
{
public function testService()
{
$mockedAnotherService = Mockery::spy(AnotherService::class);
$mockedAnotherService->shouldReceive('SetXY');
$service = new MyService();
$service->setService($mockedAnotherService);
$service->call();
$mockedAnotherService->shouldHaveReceived()->setXY(5,10);
}
}
But for some reason seems that I am unable to assert that setXY is called despite the opposite. The error is:
1) Tests\Services\MyServiceTest::testService
Mockery\Exception\InvalidCountException: Method setXY(<Any Arguments>) from Mockery_0_App_Services_AnotherService should be called
at least 1 times but called 0 times.
/var/www/html/api/vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php:47
/var/www/html/api/vendor/mockery/mockery/library/Mockery/Expectation.php:310
/var/www/html/api/vendor/mockery/mockery/library/Mockery/ReceivedMethodCalls.php:46
/var/www/html/api/vendor/mockery/mockery/library/Mockery/VerificationDirector.php:36
/var/www/html/api/vendor/mockery/mockery/library/Mockery/HigherOrderMessage.php:46
/var/www/html/api/tests/Services/MyServiceTest.php:23
phpvfscomposer:///var/www/html/api/vendor/phpunit/phpunit/phpunit:60
Do you know why that does happen?
There is a typo in:
$mockedAnotherService->shouldHaveReceived()->setXY(5,10);
Should be:
$mockedAnotherService->shouldHaveReceived()->SetXY(5,10);

Class 'App\TestService' not found - Laravel

Problem
I created service TestService, that I use in colntroller file TestController in function test().
When I called test(), I got an error:
local.ERROR: Class 'App\TestService' not found {"userId":1,"exception":"[object] (Error(code: 0): Class 'App\TestService' not found at /Backend/app/Http/Controllers/TestController.php:8)
Code
TestController.php:
<?php
namespace App\Http\Controllers;
use App\TestService;
class TestController extends Controller
{
public function test()
{
return response()->json(TestService::getTest());
}
}
TestService.php:
<?php
namespace App;
use App\TestService;
class TestService
{
public static function getTest()
{
return "test";
}
}
What I tried
I checked all the names and they are correct.
When I wrote in the colntroller file use App\TestService;
I had autocomplete, so the service and name are visible.
I used these commands to refresh the files: php artisan serve and php artisan clear-compiled.
But it still doesn't work.
You have not correctly defined Namespace.
The namespace must be a directory path where you have created a file.
TestService.php:
<?php
namespace App\Services\Tests;
class TestService
{
public static function getTest()
{
return "test";
}
}
TestController.php:
<?php
namespace App\Http\Controllers;
use App\Services\Tests\TestService;
class TestController extends Controller
{
public function test()
{
//Call service class like.
return response()->json(TestService::getTest());
}
}

Unable to use factory() in Test's setUp() method in Laravel

I've encountered an error when refactoring my Laravel tests by adding at setUp() method.
This works as expected:
<?php
namespace Tests\Feature;
use App\Models\Person;
use Tests\TestCase;
class MembershipTicketsTest extends TestCase
{
public function test_a_non_member_cannot_list_redeemable_events()
{
$user = Person::factory()->create();
$this->actingAs($user);
$this->get(route('event.index'))->assertStatus(302)->assertRedirect(route('membership.create'));
}
Where as this returns the error Unknown formatter "firstName":
<?php
namespace Tests\Feature;
use App\Models\Person;
use Tests\TestCase;
class MembershipTicketsTest extends TestCase
{
protected $user;
protected function setUp() : void
{
$this->user = Person::factory()->create();
}
public function test_a_non_member_cannot_list_redeemable_events()
{
$this->actingAs($this->user);
$this->get(route('event.index'))->assertStatus(302)->assertRedirect(route('membership.create'));
}
Every solution to this error I've found says to make sure that you have use Tests\TestCase; in your file, which I do.
I presume this means I cannot use factories in the setUp() method of a test in Laravel. Is this true, and why is it the case?

Testing a controller that extend Controller class

I'm tries instance a class that extends Controller class
This is my Controller:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class SalaryController extends Controller
{
public function calculateTotalSalary($id)
{
return $this->render('resources/view.html.twig');
}
}
and this is where I want to call the controller
<?php
namespace AppBundle\Tests\Units\Controller\Controller;
use AppBundle\Controller\SalaryController;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class SalaryControllerTest extends KernelTestCase
{
public function testExample()
{
$controller = new SalaryController;
$controller->calculateTotalSalary(1);
}
}
When executed the code give me this:
Starting test 'AppBundle\Tests\Units\Controller\Controller\SalaryControllerTest::testExample'.
PHP Fatal error: Call to a member function get() on null \vendor
symfony\src\Symfony\Bundle\FrameworkBundle\Controller\Controller.php on line 176
Line 176 in Controller class:
return $this->container->get('templating')->renderResponse($view, $parameters, $response);
the $container variable is null, Why ?

Identical class name in different files phpunit conflict

When i test my application on Zend Framework 2 i have strange error. For example, i have 2 phpunit test files:
1:
namespace Test\Model;
class Test1Test extends \PHPUnit_Framework_TestCase {
public function test1test() {
$this->assertTrue((new \Austero\Model\Test1())->t1());
}
}
2:
namespace Test\Model;
class Test2Test extends \PHPUnit_Framework_TestCase {
public function test1test() {
$this->assertTrue((new \Austero\Model\Test2())->t2());
}
}
And 2 tested model files:
namespace App\Model;
class Test1 {
public function t1() {
return true;
}
}
And:
namespace App\Model;
use
\App\Controller\Test1; // THERE USE FILE FROM ANOTHER NAMESPACE WITH SAME NAME THAT Test1 FROM App\Model NAMESPACE
class Test2 {
public function t2() {
(new Test1())->t3();
return true;
}
}
Then i got:
PHP Fatal error: Cannot use App\Controller\Test1 as Test1 because the name is already in use in /home/user/projects/app/module/App/src/App/Model/Test2.php on line 5
How can i avoid this, without change used alias? Thanks for answer

Categories