This episode is for members only

Sign up to access "Laravel Actions" right now.

Get started
Already a member? Sign in to continue
Playing
12. Mocking actions

Transcript

00:00
The great thing about actions is we can very easily mock them. So in this episode, we're going to look at an example of creating a subscription for a user,
00:09
but having an action inside of that to fetch the correct plan from a payment provider like Stripe. So we're going to get started by just building out the base functionality for this really, really quickly. So we're going to go ahead and make a model in here called subscription. Let's go ahead and create a migration and a factory for that.
00:28
And we'll go over to the create subscriptions table. We'll just make this really, really simple and just include some really basic information about a subscription that we might want to store. We won't make this a full example. So this is going to belong to a user. So let's add in a foreign user ID and constrain that. And let's go ahead and say that we want to store the Stripe ID
00:52
of the subscription. And maybe we also want an interval in here that can be something like month, year, etc. Okay, so let's go ahead and migrate these changes. And let's head over to our user model. And we'll just copy this down. And just say that user has many subscriptions, obviously, a really basic implementation of subscriptions,
01:17
but it will do for our example. Okay, so we're going to start off with our action to create a subscription. So let's go ahead and make an action here. And of course, we're going to call that create subscription, it does one thing, but this is going to use a another action to fetch the Stripe plan from Stripe via the API, we're not actually going to implement the API call,
01:40
but it would do that fetching back all of the information that we can then use to populate the data in the database. So if we open up create subscription, think about what this needs to do. So based on a Stripe ID that we pass into this handle method, it needs to get the info from Stripe. So that will be the interval, all that kind of information. Just imagine on the client
02:04
side, you're only passing in a Stripe ID, say ABC, you want to go ahead and look that up on Stripe to get more information back from there, and then use that to create this subscription properly. So then obviously, we want to create a subscription on Stripe itself, and then create the subscription locally as well. So yeah, it's doing a few things, but the overall goal is to
02:25
create a subscription, not send an email or do any of that stuff, just create a subscription. So the only thing that we're going to leave out in here is actually creating the subscription on Stripe, because we're not going to go ahead and implement a full example here. But we do need to grab the information from Stripe before we create it. Now let's think about the kind of
02:45
details we want to pass into the handle method. Probably going to need a user, of course, because we're creating a subscription for a particular user. So pull the namespace in for that. And we're going to have a string in here with the Stripe ID that gets passed in. So this might be something that you pass in via a controller. So if you wanted to, you could obviously add in an as
03:07
controller method. And then from the request you get through into here, take in the Stripe ID that comes through from the form. You kind of get the idea. We've already covered using these as controllers. So this itself is going to be an action. And then we're going to create the subscription locally. So let's just go. And before we do anything else, start to look at writing the test for this
03:30
so we can do a little bit of test driven development. So let's go ahead and say PHP artisan make test. And we're going to call this create subscription test. And we should probably put that inside of our actions folder. So let's open up create subscription test. And let's start to see what we need to do. Once again, we're going to put in the refresh database trait because we're
03:52
going to be hitting the database here. And let's come down and see what we need. So in this case, we just want to test that it creates a subscription. In reality, because we're hitting a Stripe API, this is going to be a little bit more complex. But the overall structure of this will be there. Okay, so we know what we need to do here, we need to new up a user. So we're going to use the
04:15
user factory to create a user out, then we're going to go ahead and assign the action, which is just going to be a new create subscription action to a variable. And then we know that we want to run the action. So action run, passing in that user, and then passing in a Stripe ID. And of course, we're going to kind of fake this in here, because we don't actually want to pass a
04:37
real ID. And then down here for our assertion, it can be pretty straightforward, we can just assert that we have a count of one on user subscriptions. Okay, so let's go ahead and just run this test on its own. So you PHP unit tests, feature actions, and create subscription test. And of course, at the moment, it fails. So we have zero for subscriptions. That's pretty obvious, because
05:05
we're not actually creating the subscription. Now when we create the subscription locally here, let's just go ahead and run this app subscriptions, create, what we want to do is pass in the Stripe ID, which we kind of already had have, so we can just use the Stripe ID that gets passed in. But what we want to do is grab the interval, which we can only find out with a call to the
05:27
Stripe API based on the Stripe ID. So in here, this is kind of missing at the moment. So if we go ahead and just get rid of this, our test is still going to fail because we're not inserting that data that we need. So let's go ahead and create out the action that gets information from Stripe. So how would that look? Well, let's go ahead and make out an action in here called
05:49
fetch plan from Stripe. Again, that's one thing, we can reuse this wherever we need to that might be useful to be used elsewhere. So fetch plan from Stripe. So again, we're going to make this incredibly simple. This is just going to take in a Stripe ID. And for now, let's just keep this really simple and just return an array of data. So imagine we make an API call just here, we get
06:15
back the information we need, maybe we transform it, create some kind of data object for this. So we'll just keep this really simple again, and just create an interval out in here. And just imagine that that API call gave you back a month for this Stripe ID that we pass in. That's pretty much our action. Although of course, in reality, we feel more in here. Okay, so in here, what we
06:36
can do then is use that fetch plan from Stripe running that and passing in the Stripe ID. Now, if we just die dump on plan here, and we come over to the terminal run that test, if we just go over to this, you can see we get that array back here. So what we can do is now use that to fill in the interval in here. And again, we'll just make this really simple. And we'll just use
06:58
Laravel's array helper, pull that in here. And we'll just say get, and we'll grab from the plan, the interval in here. Okay, so now when we run our test, if we just get rid of that die dump, we should see a slightly different error. And that is just the subscription details that need to be filled. So let's just set these as fillable. And that's going to be the Stripe ID.
07:28
And the interval. Great. Okay, so let's go ahead and run our test again. And sure enough, this passes. Now, this is all fine, because at the moment, what we're doing is we're just passing an interval here through as month. But in reality, what you would probably want to do is mock out the data that's actually returned from fetch plan from Stripe. So let's just make
07:53
our test a little bit more thorough in terms of what it checks. So let's go ahead and say this assert equals, and we'll just make this really, really rough. And let's say year. And let's say user subscriptions. And first, and interval. Okay, so let's say that we are signing the user up for a yearly plan. And we want to make sure that this interval is correct. Now, at the moment,
08:20
we have no control if we were mocking the data that gets returned from this particular action, what this is. So if we just go ahead and run our test now, you can see that we get a failure. So what we can actually do with Laravel actions, which is the entire point of this episode, is we can mock actions very, very efficiently. In fact, if we head over to the fetch plan from
08:44
Stripe action, and we look at this as action trait that we've already seen, you can see that we've already got an as fake in here, and we have this mock method. So we're going to go ahead and use that inside of our test to mock what gets returned from this method. And there's loads that you can do this. So once you've got the hang of this, I highly recommend you go over to the Laravel
09:05
actions docs just to check this out. Okay, so let's go ahead and say fetch plan from Stripe. And we'll use that mock method that we just saw within that trait. Now what we can do is use should receive, if we spell that correctly, and handle, because we know that in fetch plan from Stripe, we should call this. And then we want to say with, so we're passing this particular data
09:32
through to handle, which is the Stripe ID. So I'm just going to say a Stripe ID just so it's in there. And then really importantly, we're going to say and return, and we want to return some specific data. So what's now going to happen is if we say interval and year, what we're now doing is mocking this action, which is being used within, we just open up our create subscription action,
09:56
used within here. Otherwise, we wouldn't really have any control over the kind of data that's returned from this, unless we mock it in a test. So now that we've mocked that, and it's returning year, we know that by the time it comes down to create a subscription by running this, passing in a Stripe ID, which we're accepting in here, then that's going to be created with a year as the
10:19
interval. Let's run our test again, and sure enough, it passes. So if you find yourself injecting actions into the constructor, or using them directly like we've done here, within here, and you need to change around the kind of data that gets returned, it's very, very easy to mock actions with the Laravel actions package.
12 episodes1 hr 2 mins

Overview

Actions are single classes that do one thing. Laravel Actions is a package that allows you to run these classes as anything you want, whether it's a controller, listener, console command – or just on its own.

Keeping your app structure to single classes like this lets you focus on what your app does rather than the design decisions around controllers, listeners and commands.

Single actions are also easier to test, and we'll also cover that!

This course is for you if:

  • You'd like to try a fresh approach to structuring your apps
  • Your app shares logic, and you'd like to combine this logic into one class that runs anywhere
  • You've heard of (or used) Laravel Actions, and you'd like a run-through
Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!