I'm making a course on Laravel Sanctum: MasteringAuth.com

Mock HTTP requests in Laravel

Constantin Druc ยท 24 Oct, 2021

[00:03] When working with external apis, having tests making real http requests is a great way to ensure your application works correctly. However, having too many tests making network calls may lead to a slow test suite, and sometimes trading those real http requests with a couple of fake ones makes sense. Here for example, I throw an exception if the request fails. Well, I don't really need to make a real network call to test that. Same here, if the validator fails, I throw a youtube validation exception. Neither of these cases requires me to make a real http request. So let's fake them.

[00:47] I'll go ahead and create a new test called throws exception when request fails, and this test will expect an exception to be thrown, and it's this one right here: youtube request exception. Let's paste it in, import the class, and then let's grab this new youtube talk save call, paste it in, and run the test. The test isn't passing because the application makes a real http request, finds information about this real video, and then returns it; and even if I was to pass in a non-existent video id and run the test, it will still fail because youtube returns a successful response code even though the video doesn't exist.

[01:44] So let's fake that request to return a failing response. We can do that by typing http and then call the fake method. Let's import the class, and this fake method takes an array as argument, where the key is the url we are trying to call, and the value is the response we want back. For the url we can grab this part right here, paste it in, and add the star at the end. This is a wild card that it will take place of the query parameters.

[02:24] Now for the response, we can do http response, and then we can give it a body, a status code, which will be failing in our case, so 500, and an array representing the headers; but we won't need them, so I'll leave that out. Now if we run the test, it passes. So it passes because the response is a failed one and it shows the youtube request exception. If we change this back to 200, which is a successful status code, and rerun the test, it fails. So what we did here is, we intercepted the call to this endpoint and returned the response we wanted. Let's do another test for the youtube validation exception.

[03:20] So this one is for when the validator fails, we'll duplicate the test, and let's say, throws exception when youtube response data is invalid, and instead of a youtube request exception, we'll receive a youtube validation exception. And then here, the response needs to be successful, otherwise it will be caused by this check right here. And now, if we run the test, it should pass, because, well, the body is empty and we have all these validation rules. Let's instead return a valid response and see if the test still passes. So we'll do items, which will be an array, and then we'll have snippet, which will have title, description, published at, and then thumbnails, which will be an array of items that should have an url. And then we'll have player which has embedded html, and finally, content details, which has a duration.

[03:54] Let's run the test, and it should fail, because the response is valid, and it fails. But now if I remove the title, which is required, and run the test, it passes. Let's rerun the whole thing, and there it goes. But now we only have one real http request and two fake ones.