Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

majebry's avatar

Mocking a FormRequest

Hi,

I was following this guide in order to "mock" a FormRequest: https://midstride.com/how-to-mock-a-form-request-validation-in-laravel/

He has mentioned that you can mock a FormRequest by using this:

  $this->mock(UserRequest::class, function ($mock) {
     $mock->shouldReceive('passes')->andReturn(true);
  });

However, the test was throwing the following errors:

Received Mockery_2_App_Http_Requests_AdminProfileRequest::all(), but no expectations were specified
Received Mockery_2_App_Http_Requests_AdminProfileRequest::route(), but no expectations were specified

So, in order for it to work, I had to add also:

....
            $mock->shouldReceive('all')->andReturn($myRequestDataArray);
            $mock->shouldReceive('route')->andReturn(true);
....

I'm using laravel 7. Do you think I could avoid adding the last code? And why it hasn't worked as the guide declares?

Thank you!

0 likes
12 replies
bugsysha's avatar

I totally disagree with what is said in the article you've linked. I would never mock validation. If you are testing whole flow then test it. If you want things in isolation then test them with unit tests in isolation.

What I do is create a method on the test file that returns correct set of data/payload that needs to be sent with the request. That way I only have one place where I need to add that new data/payload item and move on.

andre.liem@gmail.com's avatar

Hi @majebry

I wrote the article and it's probably the version of Laravel is part of the issue or difference. If my memory serves me correctly I wrote it on 6.x, I should have noted that upfront to help.

It looks like in your scenario you have more requests being introduced in between which is adding that requirement to mock.

As @bugsysha, it is probably better to unit test the request itself on its own if that's what you are trying to achieve. I sort of make mention to that in the article actually, that if the purpose is to test something about the UserRequest class a specific test against that is more appropriate.

In my scenario, the use case I run into is that if you write a test against the controller, and don't want to test validation. This does come up, you want to perhaps test the "green" scenario where validation has passed and some code in your controller after executes. If you don't mock validation you need to setup all the proper factory inputs to ensure your controller is passing first, which can add a lot of time and isn't something you actually want to test with your controller. This is the main motivation behind the article, if there are better ways of doing it though I would love to hear it.

My personal experience was with a project that had around 15 validation fields, and setting up the test to make all of the data pass was becoming more work than the purpose of the test itself.

bugsysha's avatar

@andreliem why do you have a separate test just for food preference? Since it is same controller and same method, you can test it with your regular user update test and then you do not have to mock anything or duplicate things. If it was a separate controller then it would make sense to create a separate test and then you would not have to duplicate anything regarding validation since it would have only one thing to validate, and that is food preference.

andre.liem@gmail.com's avatar

Hi @bugsysha,

Right, that example only showed 1 field but I meant for this to be more useful when you have a request which has a lot more requirements. Probably should make that more clear in the tutorial which I may update.

The case is like imagine you have a request with 15+ request fields in it. And perhaps that request is used by multiple controllers, who knows why but that re-use was desirable.

Now you have perhaps 5-8 tests for each controller which need to prepare those records, when you don't want to test the request and instead want to test the controller itself. That's the scenario I run into.

I personally write unit tests for custom requests too, and also do this for my controller tests where I don't want to validate the request in the controller tests themselves

bugsysha's avatar

@andreliem sorry but still either I do not understand your point from that abstracted example or I still disagree with you.

Let me try to break it down. If you are mocking form request object then what is left in that controller is only business logic. So if you are only testing business logic, that should be abstracted into some class/object and should be tested in isolation. That is it. Nothing complex.

andre.liem@gmail.com's avatar

@bugsysha That's a fair point for sure, especially on the side of a pure unit testing method I agree that your idea of unit testing everything will lead to code that is well abstracted.

My question is, what about a developer who someone wants to test that an API controller calls the business logic that has been abstracted out.

e.g. - test_business_logic_is_called_with_valid_data

So a developer wants to assert that a business logic function is called from the controller when valid data is given. And the other would be that it's not called if the validation is false.

We don't want to test the validation itself, we just want to test that the controller will call the right class.

bugsysha's avatar

@andreliem that case is also covered by that test that I've wrote about when you test everything. There is no reason to doubt that test will not show you errors if they occur. Also if that test works you should not question the ability of framework to pass the call to class containing business logic. If that was the case then it would be figured out in an instant considering how many developers and companies are using Laravel. In the end there is no magic there and it boils down to plain PHP.

I think I'm starting to see a pattern here. Few years ago I was doing the same. Writing tests where I need them, and where I do not. I was writing a tests that prove a bunch of bad scenarios that I could think of just to be sure that my code is working. After a while I've figured out that I do not need to do that cause that work is never finished. You can always come up with some new edge-case that you haven't covered so my test files would concentrate on issues that prove that the code does not have any uncovered edge-cases instead of just proving the scenarios that do work. That way when you prove only the scenarios that do work, your tests are cleaner and can be used as documentation on how things work and a way for new developers to see from first hand how they should bundle things.

Hope that makes sense.

1 like
andre.liem@gmail.com's avatar

@bugsysha I think where I'm coming from is the scenario that I often like to write tests against API endpoints or controllers to test various things. Maybe you can call that integration test, I don't know what the technical terminology is but for example lets say I had an API endpoint which in my scenario updates 15 preferences for a user.

So I write up a test like it_will_store_preference_with_valid_data

This test creates the payload of 15 attributes that need to pass validation, makes the API request then checks the response to ensure it's 201. As well, it asserts the database has the appropriate values stored.

From a purist standpoint this would not be unit test by any means. It's touching a real database, validation is running when I'm not really testing that etc.

But this is a useful test for my scenarios where I want to build APIs in a TDD way.

The only problem I ran into was that when creating 15 attributes to pass validation, I need to spend time to write code which will pass validation. But perhaps I don't really want to test that and instead want to ensure the API will trigger an email.

So in my mind just mock the request to be valid, and assert an email or event is triggered.

I take it that instead of mocking the request, you would prefer injecting another class that handles validation (calls a request form), and then you mock this class instead?

I guess I should share more concrete code examples ;)

bugsysha's avatar

From a purist standpoint this would not be unit test by any means. It's touching a real database, validation is running when I'm not really testing that etc. But this is a useful test for my scenarios where I want to build APIs in a TDD way. The only problem I ran into was that when creating 15 attributes to pass validation, I need to spend time to write code which will pass validation. But perhaps I don't really want to test that and instead want to ensure the API will trigger an email.

If email is a thing that happens during that API endpoint then there is no point in testing it separately. Like I said, event is core Laravel feature and you should not worry if it works.

I take it that instead of mocking the request, you would prefer injecting another class that handles validation (calls a request form), and then you mock this class instead?

Absolutely not. No mocking. As @martinbean confirmed, if you are mocking form request, you are probably doing something wrong.

I guess I should share more concrete code examples ;)

Sure, why not. Like I said before, maybe I'm missing some piece, but I think that I just think that you are overcomplicating things.

andre.liem@gmail.com's avatar

Hi @bugsysha

If email is a thing that happens during that API endpoint then there is no point in testing it separately. Like I said, event is core Laravel feature and you should not worry if it works.

I wouldn't be testing the email itself. Okay lets say the scenario is you have the same API endpoint to update a user's preferences.

Then one day a new requirement is that an email should be dispatched after successfully saving. Maybe we decide it should be done via an event PreferencesChanged or something like that.

So in this case, I would either update my test or write a new test that asserts this event is dispatched.

e.g. - https://laravel.com/docs/8.x/mocking#event-fake

It would be mocked, so I wouldn't be testing the actual email is sent or the event really.

This seems to make sense to me, we should write tests with this type of coverage. Mocking validation to me isn't that much different, we don't want to test it in this flow necessarily, just want to mock it so that we can assert the event is being triggered if all goes through.

I can write up some concrete example if that helps.

I'm interested to learn how you and other approach testing controllers, as I find it's the messiest area but probably the most common thing to test.

bugsysha's avatar

@andreliem

I would just mock event facade and assert that the event was dispatched in that existing test. Reason why I would do it like that is cause everything that happens during that request is tested in that specific test. Also you mock the event cause things that happen on that event tend to be async and are not part of that request.

Please or to participate in this conversation.