I am using Laravel 5.3. For a procedur I am using a command. The command class is calling a method of an another class. I wanted to unit test it with phpunit. Therefore I mocked up the class within the command class. When I run the test, then the actual method of class is running and not the mocked method. Bevor I have implemented the functinality of the command in a job. There I can call the mocked method without any problem.
The test class looks like this:
class CommandTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->api = $this->getMockBuilder('App\Services\APIRepository')
->setMethods(['getStatus'])
->getMock();
}
/** #test */
public function test_api()
{
...
$this->api->expects($this->any())
->method('getStatus')
->will($this->returnValue($api_response));
\Artisan::call('myapp:tracker',[]);
...
}
}
class Command extends Command
{
protected $signature = 'myapp:tracker';
private $api;
public function __construct(APIRepository $api)
{
$this->api = $api;
}
public function handle()
{
...
$status = $this->api->getStatus(...);
var_dump($status);
...
}
}
The output of var_dump($status) is: NULL
Do I need a special method for mocking a class within a command class?
Thanks a lot in advanced!
Related
controller code
class testController extends \Illuminate\Routing\Controller
{
public function test1() {
$a = $this->test2();
...
}
protected function test2() {
return '123';
}
}
unit test code
class Test extends TestCase
{
public function unittest()
{
$mockController = \Mockery::mock('App\Http\Controllers\testController')->makePartial()->shouldAllowMockingProtectedMethods();
$mockController ->shouldReceive('test2')->andReturn('456');
$response = $this->json('GET', action('testController#test1'));
$response->assertStatus(200);
}
}
when do unit test, test2 method always return 123, not 456
Anything help? Thanks.
It's not clear what $this->json() does internally (it's not a part of plain PHPUnit), but anyway, the problem is probably that you don't inject your $mockController anywhere, and thus the original controller is requested by unit test.
I am currently writing a test to test a model method.
My model Store has this method:
public function hourTemplate() {
return $this->belongsTo(HourTemplate::class);
}
I have a test as well with this code in setUp method:
public function setUp() : void
{
parent::setUp();
$this->storeMock = Mockery::mock(StoreModel::class)->makePartial();
app()->instance(StoreModel::class, $this->storeMock);
}
And test method is like this:
public function test_getStoreHoursArray_when_hour_isNull() {
$this->storeMock->shouldReceive('hourTemplate')->andReturn(new HourTemplate());
dump((new StoreModel())->hourTemplate);
}
But the returned value is null.
You should retrieve the mocked instance from the container
$mockedModel = app()->make(StoreModel::class);
How can i test my function which has __construct ?
For ex my controller code looks like :
namespace App\Http\Controllers;
use App\Repositories\UserAccountRepository;
class UserController extends ProtectedController
{
protected $userAccountRepository;
public function __construct(userAccountRepository
$userAccountRepository){
parent::__construct();
$this->userAccountRepository = $userAccountRepository;
}
public function FunctionWantToTest(){
return 'string';
}
The unit test required to fulfill the construct first before test my FunctionWantToTest.
So, my test code looks like,
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Http\Controllers\UserController;
class UserTest extends TestCase
{
/**
* A basic test example.
*
* #return void
*/
public function testUserList()
{
$UserController = new UserController(???what value??);
$this->assertTrue(true);
}
}
Need more help (best practice) how to test the code which has construct.
I think you just need to use app->make:
class UserTest extends TestCase
{
protected $userController;
public function setUp() {
parent::setUp();
$this->userController = $this->app->make(UserController::class);
}
/**
* A basic test example.
*
* #return void
*/
public function testUserList()
{
$this->userController // do what you need here...
$this->assertTrue(true);
}
}
Use feature test or integration test when test controller,
You can see this brief explanation about unit test and integration test.
What's the difference between unit tests and integration tests?
all.
For a Laravel project I'm working on, I've started to use Dependency Injection in order to mock classes in my tests. However, I've found that if I try to inject into a custom class with no explicit parent, two things are true:
The dependency injection works correctly when running the application
The injection fails when running tests in PHPUnit
Here is some sample code similar to what I'm using:
DemoController
// The controller we're testing
class DemoController extends Controller
{
// The injection and constructor
private $helpLayer1;
public function __construct(HelpLayer1 $helpLayer1)
{
$this->helpLayer1 = $helpLayer1;
}
...
// The test function I call
public function testDeps()
{
$this->helpLayer1->testLayer1();
}
}
HelperLayer1
// Our first helper class
class HelperLayer1
{
private $helpLayer2;
public function __construct(HelpLayer2 $helpLayer2)
{
$this->helpLayer2 = $helpLayer2;
}
...
// The testing function
public function testLayer1()
{
// When called via route, this dumps the actual object
// When called via test, this returns null
dd($this->helperLayer2);
}
}
Helper1ServiceProvider
class Helper1ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer1', function()
{
return new HelperLayer1(App::make('HelperLayer2'));
});
}
[OR]
public function register()
{
$this->app->bind('HelperLayer1', 'HelperLayer1');
}
}
Helper2ServiceProvider
class Helper2ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer2', 'HelperLayer2');
}
}
I'm relatively new to using DI, so I'm not entirely sure that this set-up is correct, but I'm at a loss.
Any help would be greatly appreciated! Thank you!
When my very first unit test class is run, why is the Session class not available in setUpBeforeClass? After the first unit test class has finished, the session class is available in setUpBeforeClass.
Is there something I can do to make sure that Session is available in my first unit test?
<?php
class AATest extends TestCase
{
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
\Session::put('tenantId',100); // <-- this fails
\Session::put('userId',1100);
}
public function setUp()
{
parent::setUp();
\Session::put('tenantId',100); // <-- if removed from before class, this works.
\Session::put('userId',1100);
}
public function test1()
{
$tenantId = \Session::get('tenantId');
$userId = \Session::get('userId');
$this->assertEquals(100,$tenantId);
$this->assertEquals(1100,$userId);
}
}