How to mock User model within composer package development tests? - laravel

I started creating a laravel 5.8 based modular API framework for our company which should be extended using composer packages.
Now I stumbled over the problem to test each package by itself (each package has it's own GIT project of course) if the package needs to have access to the User model given in the base framework (App/Models/User).
There will be various packages naturally depending on the User model such as specific auth modules.
Unfortunately testing also gets more complex because we are using GraphQL (Lighthouse).
So how should this be done? I tried mocking App/Models/User with a User model contained in the tests folder of my package, but this did not work as expected:
$this->userMock = \Mockery::mock('CompanyName\\PackageName\\Tests\\User');
$this->app->instance('App\\Models\\User', $this->userMock);
When, after that, posting a GraphQL request the resolver method throws a Class App\Models\User does not exist error.
I am quiet new to testing with phpunit so maybe I am just missing something here?
Edit:
I just found out that the error message above is displayed because the User model is also referenced within the GraphQL schema file.
So I there is any solution out there it has to somehow "emulate" the not existing User model class for the whole request lifecycle I guess...

Ok I finally solved my problem which was more conceptual wise I guess. As the user model is pretty strongly tied to the (core) package I want to test, I have now moved the model into the package itself and removed it from the base project.
This has the advantage that the "end user developer" doesn't even see and has to cope with the user model which is handles by the package anyway.
Now I can test the package independently and only have to put a line of documentation into the README to tell, that a user has to change the auth.providers.users.modelvalue to let laravel use the appropriate model (e.g. CompanyName\\PackageName\\Models).
If there will be other packages extending the user model, they will have to depend on the core package (which they should either way) and can extend the model class and tell the user to update auth.providers.users.model again. This way it is also quiet transparent to see which user model is used currently.
For the GraphQL / Lighthouse part I have added the following code to the boot method of the package's service provider to make lighthouse know about new models within the package automatically:
$lighthouseModels = config('lighthouse.namespaces.models');
array_push($lighthouseModels, 'CompanyName\\PackageName\\Models');
config([
'lighthouse.namespaces.models' => $lighthouseModels
]);
This can be repeated for every package adding models as well so lighthouse knows about all of them.

Related

AsyncCrudAppService Breaks Swagger When Providing TCreateInput and TUpdateInput

I recently downloaded a Single Page Web Application (Angular) from https://aspnetboilerplate.com/Templates using 3.x target version.
I just simply added a few entities and then started to follow the steps on this page https://aspnetboilerplate.com/Pages/Documents/Application-Services
Things do work well for me to Get, List, Update, and Delete entities when my app service class is just inheriting AsyncCrudAppService<Entities.PhoneBook, PhoneBookDto, long, GetAllPhoneBooksInput>, however when it is inheriting AsyncCrudAppService<Entities.PhoneBook, PhoneBookDto, long, GetAllPhoneBooksInput, CreatePhoneBookInput, and UpdatePhoneBookInput> the swagger definition will no longer load.
GitHub Repo: https://github.com/woodman231/MyPhoneBooks
(which currently does not work and will not load Swagger page).
I can get the swagger page to load by removing CreatePhoneBookInput and UpdatePhoneBookInput from
https://github.com/woodman231/MyPhoneBooks/blob/main/aspnet-core/src/MyPhoneBooks.Application/SimpleCrudAppServices/ISimplePhoneBookCrudAppService.cs#L9
and
https://github.com/woodman231/MyPhoneBooks/blob/main/aspnet-core/src/MyPhoneBooks.Application/SimpleCrudAppServices/SimplePhoneBookCrudAppService.cs#L14
However, again I am still unable to create entities using this default implementation. Any ideas?
I have cloned your repo and run it and I figured out the error, first as I tell you in comments I verified the text log, and it said the next:
System.InvalidOperationException: Can't use schemaId "$CreatePhoneBookInput" for type "$MyPhoneBooks.SimpleCrudAppServices.Dtos.CreatePhoneBookInput". The same schemaId is already used for type "$MyPhoneBooks.PhoneBooks.Dtos.CreatePhoneBookInput"
What happenig is that you have these two classes UpdatePhoneBookInput, CreatePhoneBookInput repeated in SanokeCrudAppServices\Dtos and PhoneBooks\Dtos
You have the classes in both folders with same exact name, and thats the problem, if you change the name in whatever place the swagger definition will load without errors, I have do it like this and everything works fine!
Change the name in one of the places, and all will be working fine
Personally I don't like to use a different Dto for Create and Update for me is easier to user just one Dto for all.
Ok I figured it out. I had also made a DIY AppService and some of the DTO Class Names associated with the DIY App Service clashed with the DTO Class Names associated with the Automated Service. It was acceptable in .NET since they were in different name spaces but once the swagger definition was configured I assume that there was multiple instances of the same DTO Defition. I checked the AbpLogs table but they didn't give me much details as to the specifics of the internal server error while loading the definition. It sure would have been useful to know that.

How to override any Model of vendor folder in laravel

I am using MongoDB as database so I need to change model of package tzsk\payu as using original is giving me following error
Call to a member function prepare() on null
I tried excluding original model and overriding using composer it doesn't work.
The only way would be if the package offered the option to use a custom model, like Passport is doing.
As far as I can see, there does not seem to be a way to do that. Thus you'd need to fork the package and edit the Model yourself.

Laravel Auditing AuditableTransitionException Error on Morphmap on transitionTo()

I am able to successfully record changes to classes, and return what has been changed (not including many-to-many). However, I am unable to revert back any change using the built-in new transitionTo() method.
I get the following error on all classes:
Expected Auditable type App\XYZ, got XYZ instead
I have all of my morphable classes (which are all I am using for tracking audits) attached correctly within AppServiceProvider in a morphmap like so:
\Illuminate\Database\Eloquent\Relations\Relation::morphMap([
'Employee' => \App\Employee::class,
];
All classes work correctly with all other Laravel morphTo methods.
The auditable code looks like it is tripping the error in line 467 of the Auditable class:
if (!$this instanceof $audit->auditable_type) {}
It doesn't appear to be looking to the map for any of the morphed classes. Or, I could be totally missing something of course!
Any help on how to get this to work using the auditing method -- has anyone gotten this to work with standard morph classes? (It will of course revert the class manually by looping on the old fields and saving the object).
Using Laravel 5.5 and the latest version (5.0) of Laravel-Auditing.
Sent a note to the developer - this was in fact a bug. Vendor code was needed to include morphMapped objects.
Developer at Laravel Auditing responded within an hour and had a fix a few hours later. I can confirm this is now functioning as expected. Outstanding support.

Where does one place Models in a Laravel Package?

I'm currently following the Laravel Package documentation, which uses the workbench tool to create a standard package tree consisting of controller, config, views, etc. folders. Basically, most folders you would get in a standard Laravel app tree.
However, I had a couple of questions:
Why is the models folder absent here? (though the same goes for tests and commands)
Should I just create the folder myself and add it to the composer.json autoload classmap?
What classes should live inside src/<Namespace>/<PackageName>? I have noticed that a ServiceProvider is automatically created here, but I can imagine most other files just existing in the standard package directories.
Wockbench represents just a tool for creating other tools, that is triggered through CLI. Workbench is very abstract concept.
Model folder is absent simply because you don't need model in every new package. For example, if you are creating middleware package or you own filter package.
Every new class can be added to package dependent on its purpose and responsibility. It can be done in more then one way.
Classes that are general enough to go into every package are:
Package Service Provider
Facade
Basic Class
But it is not a black box. Consider for example request class - it is bound very early in the application life cycle, so no provider is needed.

using doctrine with codeigniter

I am planning to use doctrine to write a module of my app which is built with codeigniter.
I have a very basic question :
lets say I have a table called "user", with doctrine generate-models from db, 3 classes are generated BaseUser.php, User.php and UserTable.php. Now as I saw in the examples they use User class straigtaway. Should I be doing this ? I need additional business functionality for the user objects. So should I create a codeigniter model user_model and then use User class inside it (aggregation) or somehow extend user class ( i dont know how this will be done as user_model extends model)
Am little confused on this one and cannot locate any appropriate literature for the same.
Any help would be appreciated.
thanks in advance,
For anyone who is interested - I’ve posted up a project starter on my blog - a dev ready incorporation of the following technologies:
ExtJS : client side JS library,
CodeIgniter : presentation + domain tier,
Doctrine : ORM data layer framework
Some features of this project starter are:
- CodeIgniter Models have been replaced with Doctrine Records
- Doctrine is loaded into CI as a plugin
- RoR type before and after filters….
- Doctrine transactions automatically wrapped around every action at execution time (ATOMIC db updates)
Basic Role based security (I think Redux may be in there as well?)
Simply extract, hook up the database.php config file and viola…. You can start coding your layouts, views and models. Probably a few things to iron out - but enjoy!
Hope it helps
GET IT AT: http://thecodeabode.blogspot.com
Check out this info on Doctrine_Table class.
To your 3 generated files:
BaseXXX.php:
Holds the definition of your models so that Doctrine is able to handle the operations on the database. This class tells the ORM what colums are available, their types, advaned functions (like Timestampable,...) and more. You should not put your own data into this file since it will be over-written when re-creating the models from the database.
XXX.php:
Your actual model. This won't be re-created with each new generation process and this is were you keep most of your code. You can overwrite functions of the BaseXXX.php if you have to.
XXXTable.php:
Check my link from the top, This gives you access to the table itself. Personally, I do not use it that often since I put most of the code into XXX.php.
Of course you can create new classes and use them inside your XXX.php file. In order to actually do something with the data (save, read,...) you need classes that are connected (exteneded) from Doctrine's classes.
edit: also check this on a more infos with extending from the Doctrine_Table class

Resources