ideas
ideas copied to clipboard
Add ability to unfake facade
It will be great to be able to unfake the facade: Bus::unfake();
If I call Bus::fake() , then there is no proper way to revert this, I have to make new Dispatcher and swap the fake with original.
If you need to fake only a specific subset you can bass an array to fake method in order to let you use others jobs.
Also you can split your test into multiple tiny tests instead of relying on a big one with one Bus::fake()
Never had the need to unfake, maybe it's a code smell of a big test that can be refactored
@ludo237 , for example I have several tests and more of them create model via factory and there is an observer which observe the model and make some operations(run jobs and etc.), so I need ability to fake the job in all tests except one where I will test the job after model was created via rest.
You should create your mock without the observer in place if you don't need that in a specific test
User::withoutEvents(function() {
return factory(User::class)->create(); // Or whatever you use to mock
});
This way you create your model via factory and then you can test your jobs on your REST Http test
Checkout the API here
I even added a helper in my test suite for this:
/**
* Saves the given models without any events
*
* The event disable/enable logic is from
* https://laravel.io/forum/09-14-2014-turn-off-eloquent-events?page=1#reply-29610
*
* @param Model $model
* @return void
*/
protected function modelSaveWithoutEvents(Model $model): void
{
$model::withoutEvents(function () use ($model) {
$model->save();
});
}
@ludo237 I need observer creating method, not the saved method. Anyway, I need fake the job, not the events.
I'll try to explain - There is a job and observer which call the job and I need to fake the job in all tests except one test. I call Bus::fake(MyJobClass); and in my test I want unfake(or remove the job from fake list) to have ability to test the job(no unit test, I need test it via rest)
I need to fake the job in all tests except one test.
If you have different tests you can call Bus::fake(MyJobClass::class) in every tests except the one when you need it.
Basically if you have a setUp method inside your test with Bus::fake() then move it down to every method where you need to fake it except the one where you don't need it
@ludo237 Yes, I can do it, but it will be elegant to have ability to unfake job for the test.
@idsulik mixed feeling about it. I'd like to see each test in isolation from other tests. That's why I try to avoid using setUp and tearDown when not necessary.
I'd rather create a separate test or a class of tests specifically for mixing different domains if needed
@ludo237 , for example, I have several tests that use User model, each of the tests need it, so I prefer create that user in setUp method of the base test class.
The user model has events that run job, I need fake the job but in one test I want to have ability to run job and test it
Here's an example of how to make this work.
In your setUp() do this...
$this->realQueue = Queue::getFacadeRoot();
Queue::fake();
Then later in a test you can do this...
Queue::swap($this->realQueue);
I hope this helps someone.
Thanks for your example @rmcdaniel!
In my case I had to re-enable Eloquent model events so in my setUp() I used:
$this->realEvent = Event::getFacadeRoot();
Event::fake();
And later:
// use Illuminate\Database\Eloquent\Model;
Model::setEventDispatcher($this->realEvent);