Laravel unit testing calling a method that calls that database - laravel

I have been trying to set up a unit test that calls a method where the database is called. I have looked up mocking and faker and am confused about what to do.
In my test I call
Logic::lookForClassificationException($exception_array, $content);
In my method there is a call to my ClassificationException model
$exceptions = ClassificationException::select('exception')->get();
I am confused about how to set up a mock for this. ClassificationException is a table that has an id, exception, previous_word, and after_word.
How do I mock or fake the setup?

One way to do tests using DB is to setup an in memory sqlite database for tests like so:
use Illuminate\Database\Capsule\Manager as DB;
protected function setUpDatabase()
{
$database = new DB;
$database->addConnection(['driver' => 'sqlite', 'database' => ':memory:']);
$database->bootEloquent();
$database->setAsGlobal();
}
Then, call this function in your setUp method of the test class.
This is just one of many possible ways and may not suit your needs. Another way would be to setup a separate database for tests and use a separate .env for tests
In my experience, tests break down when you try to mock Eloquent models

Related

Mockery Laravel Elequent chained queries

I have a question regarding mockery in combination with Laravel.
I have sucessfully created a mockery object to mock all the public static methods such as where and find on the elequent model instance.
$userMock = \Mockery::mock('alias:App\Models\User');
This works great, however testing chained queries like I ran into some issues:
User::where("name", "test")->first()
The only solution I could find is to use mock the demeter chain using: http://docs.mockery.io/en/latest/reference/demeter_chains.html
So for example:
$userMock->shouldReceive('where->first')->andReturn($user);
But I would like to test the arguments that are provided to the where query as well:
$userMock->shouldReceive("where")->with("slug", "test")->andReturn($user);
But that is not really working since it should return the Elequent builder, any ideas how I can test this properly?
$userMock->shouldReceive('where')
->with("slug", "test")
->andReturn(Mockery::self())
->shouldReceive("first")
->andReturn($user);
Using Mockery::self you can complete the chain.

How work the test in laravel with model route

How best to build with testing this way.
I would like to test everything to the point of no return. Now I just want to select a BillingDetail for this I have the route
Route::post('/user/billingDetail/select/{billingDetail}', [BillingDetailController::class, 'select'])->middleware(['auth:sanctum', 'verified'])->name('user.billingDetail.select');
and here once my test I have tried:
public function test_can_user_select_billing_detail_as_default() {
$response = $this->actingAs(self::$user)->post('/user/billingDetail/select/', [self::$billingDetail]);
$response->assertSuccessful();
}
the problem here is that the route needs a {billingDetail} but what should I do, I have to pass it with how can I do that best. The route needs the model BillingDetail.
there are various ways to do it, according to me you can:
create the billing detail in your setUp function in order to make it usable by multiple tests in that test class.
add the billing detail to a protected property of the class extended by your test class, (Illuminate\Foundation\Testing\TestCase in Laravel), and then use that property in your tests.
use a dataProvider, if you have multiple billing details.
do as you did, but remember that the parameter should be like
['billingDetail' => $yourBillingDetail].
you can persist a faked billing detail with a factory
BillingDetail::factory()->create()

Laravel Passport create clients programmatically

Is there a way to create clients from user interface in Laravel? If I need to allow users to create and manage their own clients, how can I run "passport:client" in a function context in order to create a client on the fly?
I tried by making a OauthClient model and implementing a form that generates the client, but the so created clients are not recognized in requests (they are random strings of 40 characters).
I strongly recommend looking at the source code where the command is handled (and maybe this gist)
There is no need to create an own model class! You can create new clients programmatically by using the Laravel\Passport\ClientRepository class. Simply take one of these options:
Use dependency injection
You can inject the ClientRepository class into your controller/route functions. E.g. in the routes/web.php:
Route::get('test', function (\Laravel\Passport\ClientRepository $clientRepository) {
$clientRepository->create(null, 'MyTest', 'https://example.com/auth/callback');
});
Use the app() helper
In fact also dependency injection but callable from any place of your code, you can use the app() helper:
$clientRepository = app('Laravel\Passport\ClientRepository');
$client = $clientRepository->create(null, 'MyTest', 'https://example.com/auth/callback');

Mocking a Laravel Facade that calls a method from the Facade itself

I'm currently in the process of writing unit tests for a Trait. This Trait included a method called registryPersist() which in tern calls a Facade method called Registry::persist(). This method as the name implies saves the registry value to the database and then calls Registry::set() in order to set the registry to the local scope. It is a fairly straight forward procedure.
I tried following the suggestion from the Laravel docs and mocking the Registry::persist() method with the following code:
Registry::shouldReceive('persist')->with('test', 'ok', 'model.users')
However given that persist also calls set i get the BadMethodCallException exception because set is not mocked. (Received RegistryAccessControl::set(), but no expectations were specified)
The official mockery docs suggest to create a mock instance how ever this will not work because when i actually try to call the Trait method, the facade is not mocked.
$user = factory(User::class)->create();
$user->registrySet('test', 'ok');
The Trait Method:
public function registryPersist(string $name, $value): void
{
Registry::persist(
$name,
$value,
$this->getNamespace()
);
}
Is there any way to effectively test this method?
Furthermore, given that registrySet() only forwards the parameters to the Facade do you think that the test that im trying to write is a good idea?
Thanks in advance.

How to check in laravel if a method of some service is called in codeception functionall test

I have a codeception cest test in which I want to check if some method is called.
public function my_test(FunctionalTester $I)
{
$I->authenticateTestUser($I);
$this->fillKomitentForm($I, 'kom1', 'Komitent 1');
$I->click('btnSave');
// Here I want to check that MyService.myMethod() is invoked
}
I can make a helper but anyway I do not know how to assure that some method on some object is called. Take into account that this is Laravel 5.2 and that those services are bind using service providers.
Try to use AspectMock.
One of the features is Create test doubles for class methods called anywhere.

Resources