'How to Mock the Request Class in Laravel?
I'm trying to test a function that depends on
$request->all();
in a method. How do I mock the Request class so $request->all();
returns
['includes' => ['some_val','another_val']
in tests?
Solution 1:[1]
I recommend you to use mockery/mockery
.
I don't remember right now if Laravel comes with it or not (I think yes).
Either way, you will have to do this:
In your method test do:
app()->bind(\Illuminate\Http\Request::class, function () {
$mock = \Mockery::mock(\Illuminate\Http\Request::class)->makePartial();
$mock->shouldReceive('all')->andReturn(['includes' => ['some_val','another_val']]);
return $mock;
});
What you are doing there is:
- Binding the mock to the Request, so when you do
yourMethod(Request $request)
it will instantiate your mock instead of the real class. - Doing
\Mockery::mock(CLASS)->makePartial();
will first create a mock of that class, and then (makePartial()
) will allow you to use other non-mocked methods to be usable (use real methods) so any method you didn't mocked will run real code. shouldReceive
will allow the mocked class to use mock the method (argument ofshouldReceive
), so we are mockingall
method and return your desired value, in this case, the array you posted.- And finally we must return the mock as the instance.
As @devk stated, Laravel does not recommend mocking Request
class, so don't do it, but if you need to mock any other object, you can use code above and it will work perfectly.
Solution 2:[2]
Per https://stackoverflow.com/a/61903688/135114, if
- your function under test takes a
$request
argument, - you don't need to do funky stuff to the Request—real paths are good enough for you
... then you don't need to "mock" a Request (as in, mockery),
you can just create a Request
and pass it, e.g.
public function test_myFunc_condition_expectedResult() {
...
$mockRequest = Request::create('/path/that/I_want', 'GET');
$this->assertTrue($myClass->myFuncThat($mockRequest));
}
Solution 3:[3]
As stated by devk, don't mock the request. But Laravel allows you to build an actual request and then call your controller in your test like this:
public function testPostRequest() {
$response = $this->post(
'/my-custom-route',
['includes' => ['some_val','another_val']]
);
}
Solution 4:[4]
This works well, for a mock or you can do as above with the partial depending on if you want the request object to pass around or inspect
/** @var \Illuminate\Http\Request|\Mockery\MockInterface */
$request = $this->mock(Request::class, function (MockInterface $mock) {
$mock->shouldReceive('all')
->once()
->andReturn([
'includes' => [
'some_val', 'another_val',
],
]);
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | thisiskelvin |
Solution 2 | Daryn |
Solution 3 | Christopher Thomas |
Solution 4 | Garrick Crouch |