Reputation: 62326
The closure in the code below has made this code very difficult to test. How can I continue to eager load these items and maintain full testability?
public function scopeWithCompanyPreferences(Builder $builder)
{
return $builder->with([
'companies' => function ($query) {
$query->with('companies');
$query->with('preference_settings');
$query->with('parent_company');
}
]);
}
I've seen using Mockery the use of Mockery::on()
, but I don't think that's useful given the array.
Upvotes: 5
Views: 2442
Reputation: 113
However old this could be, I would like to expand the accepted answer.
I was having hard time writing a similar sort of test, and one thing that I've been missing was that $x['companies']
(as per this example) is a function that is called in a with
. So if you need to test what's within that closure, you should write your expectations within a \Mockery::on()
, and call the closure in the end, finally returning true
.
So, having this code:
$builder->with([
'companies' => function ($query) {
$query->with('companies');
$query->with('preference_settings');
$query->with('parent_company');
}
]);
A test would look like this:
$mockBuilder = \Mockery::mock(Builder::class);
$mockBuilder->shouldReceive('with')
->once()
->with(\Mockery::on(function ($relations) {
$mockSubQuery = Mockery::mock(Builder::class);
$mockSubQuery->shouldReceive('with')->once()->with('companies')->andReturnSelf();
$mockSubQuery->shouldReceive('with')->once()->with('preference_settings')->andReturnSelf();
$mockSubQuery->shouldReceive('with')->once()->with('parent_company')->andReturnSelf();
$relations['companies']($mockSubQuery);
return true;
})
->andReturnSelf();
What I was trying was like this, which didn't work (as per the example):
$mockBuilder->shouldReceive('with')
->once()
->with(['companies' => \Mockery::on(function ($query) {
$mockSubQuery = Mockery::mock(Builder::class);
// assertions
$query($mockSubQuery);
return true;
}])
->andReturnSelf();
Hope this helps.
Upvotes: 1
Reputation: 15740
If you're mocking the with
method, you should be able to use Mockery::on()
like this:
$b = \Mockery::mock("your_builder_class");
$b->shouldReceive("with")
->with(\Mockery::on(function($x){
// test $x any way you like, for example...
// ...a simple check to see if $x["companies"] is a function
return is_callable($x["companies"]);
}))
->once()
->andReturn("hello!");
Upvotes: 5