در حال بارگذاری ...

Introducing Facade Fakes0:00

Here's a quite new feature that was added to Laravel 5.3. A number of the facades can now be faked. And I will explain what that is in a minute. But real quick, take note. So when you do things like event fire, yeah, this is the class you'd be referencing. And you'll now see that in Laravel 5.3, you have a fake method on it. Let's take a look at another one. How about the Notification facade? Yep, that has a fake method as well. What about Queue?

What a Fake Is0:23

Yep, that has a fake method as well. What about queue? Yep, there it is. And then maybe one more. How about the Mail facade? Yep, we have that there too. Okay, so what exactly is a fake? Well, it's a form of a test double where you create a very light implementation of an existing class. So for example, if we go to event, well, you may know that Laravel uses the Illuminate\Events\Dispatcher class.

So for example, if we go to event, well, you may know that Laravel uses the Illuminate\Events\Dispatcher class. So even if you do things like event::fire, that's just a facade, right? Behind the scenes, it's calling a fire method on this dispatcher class. And you'll find it right here. Now, what a fake is, well, it's specifically for testing. It's a light implementation of a contract or some API that can be used to simplify your tests. So as you can imagine, sometimes if you're testing a route or a class, you don't actually want to fire the event; in this case, maybe you just want to say, I expect the event to be fired.

you don't actually want to fire the event in this case. Maybe you just want to say, I expect the event to be fired. But I don't want to trigger all of these different listeners, because I'm not interested in that right now. I just want to make sure that I do fire an event. So you can either do that by, in your tests, doing expect events, or you can now use these fakes here. So here's what's happening. When we call eventFake, behind the scenes, that's going to swap out the underlying class that's associated with this facade and replace it with a fake version.

When we call event fake, behind the scenes, that's going to swap out the underlying class that's associated with this facade and replace it with a fake version. And by the way, for your own tests, you can always create your own fakes. Sometimes that's a good way to go. Not always necessary, but sometimes you may find that it simplifies things quite a bit. So anyways, you'll see that this fake version of the event dispatcher does conform to the interface. So you'll find things like fire, listen, until, all of that stuff. But you also see that TaylorOtwell added a handful of assertions onto this. So that means we could do something like this.

Asserting Events Fired2:45

Let's see. All right, here's the two. And you're going to find that for each facade, you'll probably have different assert methods. So let's see, like, is there a Q\Fake? assert, yeah. So the assertion methods will, of course, relate to whatever it is that the class does. In this case, assertPushed. But for event, it would be assertFired. Okay, so that means I could say something like this. Event::assertFired.

Okay, so that means I could say something like this. Event, assertFired. Now, what is the event? Let's create one really quick. Let's say we have an event called UserBecameForeverSupporter, like it Laracasts. Okay, so now, of course, you'll see that within events right here. Next, we can say, I expect that event to be fired. So let's grab that, import it at the very top, and then reference it as a string. Okay, so let's just leave it like that. I'm going to run phpunit, and it's going to fail, right?

Okay, so let's just leave it like that. I'm going to run phpunit, and it's going to fail, right? So we expected this event to be fired, but it wasn't. Good. So why don't we do something to trigger the event? Like, let's visit maybe some fake route that all it's going to do is fire an event. But in real life, maybe you hit the registration page, and you test that. Or maybe you're testing another class individually. You're newing up a class that will fire the event. Whatever you want to do there.

You're newing up a class that will fire the event. Whatever you want to do there. So visit events. And I'm going to switch to my web.php routes file. When we hit that route, all it's going to do, once again, is fire this event. So new User became forever supporter. I will import that at the top. And then I will just say return done. And if we run it again, we do get green. And that's because, once again, we've swapped out the underlying event dispatcher.

And if we run it again, we do get green. And that's because, once again, we've swapped out the underlying event dispatcher with the fake version. So now, take a look. When you call fire, it's saving it to an events array, but that's it. And you'll find that even other methods don't need to do anything, like subscribe, or push, or listen, or a lot of these. So then, we can perform expectations on that. Assert::fired. Here we go.

Validating Event Data4:50

Assert fired. Here we go. We're just using a simple php unit assertion, where you give it the event, and then an optional callback if you need to drill down to make sure that the event class actually contains the data you expect. For example, what if I want to make sure that a specific User did become the forever supporter? So, for example, like we could say user. Let's just grab the first one. Maybe that's the authenticated user or something like that.

Let's just grab the first one. Maybe that's the authenticated user or something like that. Well, I could say the event that was fired, I want to make sure that it matches up with this user. So I could return $event->user_id equals $user. OK, so let's try this out, and it's not going to work. So I run it, and it says undefined property $event->user. And that's because, right here, we haven't accepted a user. So let's do that now. This, of course, will be the user who upgraded their subscription.

So let's do that now. This, of course, will be the User who upgraded their subscription. All right, but it's still not going to work, right? It now can find the User, but nothing matched up. Missing argument one for the constructor. OK, so now we go back to our web.php file, and when we fire this event, we have to pass through the User. And once again, this may come from the request. It might be your authenticated User. It doesn't matter.

It might be your authenticated user. It doesn't matter. OK, so now, if we run it, we get green again because everything matched up. And this can be pretty useful. So we wanted to make sure that, yes, an event was raised, but also, I want to make sure that the user who upgraded their subscription is, in fact, the one we expect. So we take the event, E. Really, this kind of has some overlap with JavaScript's E object. But in this case, E literally refers to an instance of this class.

Really, this kind of has some overlap with JavaScript's E object. But in this case, E literally refers to an instance of this class. So we're grabbing the user, grabbing their id, and we're just making sure that id is the id of the user we expect. Now, of course, we could say assertNotFired. So we could do something like this, and that's going to fail, right? Because we didn't expect the event, but it was fired. And you'll do this probably in situations where you have some kind of condition where you check if this happens to be the case, we're going to raise an event or fire off an email or do something like that.

Faking and Asserting Mail7:00

where you check if this happens to be the case, we're going to raise an event or fire off an email or do something like that. Otherwise, we're not. So you can test that flow through your system using assertFired and assertNotFired. So we would need to turn this off entirely to get it back to green. Okay, why don't we review just one more, and then I'll let you figure out the other ones on your own time. It's all basically the same format. So let's say it fakes events. Why don't we say it fakes Mailables?

So let's say it fakes events. Why don't we say it fakes Mailables? All right, so it's going to be basically the exact same format. We go to our Mail facade. We can see that there is a fake method. So that defers to an alternate implementation. And once again, it will conform to the API. But notice when you call send, yeah, this is our fake. It's our very light implementation. It doesn't even have to do anything.

It's our very light implementation. It doesn't even have to do anything. We don't actually want to fire off an email. We just want to, in this case, maybe record it so that we can perform assertions later. And in this case, our assertions are these three: AssertSent, AssertSentTo, and AssertNotSent. So let's make sure, let's do a test to see if, or to ensure that an email is sent to somebody. All right, so we first begin by saying Mail::fake(). That's always the first step.

All right, so we first begin by saying Mail::fake. That's always the first step. You have to swap out the underlying implementation with the fake version. If you don't do this first, it's not going to work. Okay, next we're going to visit a page that will send some kind of email. And then finally, I'm going to say, and which method do we want? assertSentTo. Now, once again, we need some kind of User. So I will fake this, so to speak, no pun intended. And we expect an email sent to this User.

So I will fake this, so to speak, no pun intended. And we expect an email sent to this User. Or you could even pass a collection of Users, and it will correctly verify those as needed. Okay, so let's run our test, and it's going to fail. Let's see what the problem is. Not found exception. Not found exception. Okay, and that's because this route doesn't exist. Let's create it, or let's just replace it.

Okay, and that's because this route doesn't exist. Let's create it, or let's just replace it. All right, run it again. And now it fails, missing argument two for AssertSentTo. Okay, so what's the problem here? It wants us to reference the name of a Mailable class. So let's imagine that we have one. In fact, let's just create one. Let's make a mail class, and we'll call it Welcome. Okay, now we have that here.

Let's make a Mail class, and we'll call it welcome. Okay, now we have that here. So we've already reviewed Mailables in this series. If they're brand new to you, go back and watch that episode. In this case, though, we could say view. Why don't we change that to emails.welcome? And behind the scenes, I've already created that. So emails.welcome, it's just a quick little stub there. So that's the email we'd fire off. And of course, we can accept anything through the constructor that we need to.

So that's the email we'd fire off. And of course, we can accept anything through the constructor that we need to. Okay, so now we're going to give it the name of the mailable class, Welcome. And once again, I will import that at the top, like so. Okay, so if we run it again, it's still going to fail, but we would expect this to. We expected this email to be sent, but it was not. Okay, let's fix that. We're going to come back, and we'll say, this time, mail to this user. send, and then we will new up a Welcome email and import that at the top.

We're going to come back, and we'll say, this time, mail to this User. Send, and then we will new up a WelcomeEmail and import that at the top. All right, let's run it, and we get green. It worked. So we remove it. The mail is not sent. The test expects it to be sent, so it fails. But you add the email. It runs properly. We don't fire it off, so it's not going over SMTP.

Wrap-Up and General Pattern10:36

It runs properly. We don't fire it off, so it's not going over SMTP. In fact, as we learned, when you call send, absolutely nothing happens behind the scenes. And you'll see, if we call the to method, this is where that gets registered. But anyways, that's about all there is to it. You're going to have this for queues, for notifications, for mails, for events, lots of stuff like that, and it's really intuitive. Just remember, once again, you have to swap out the underlying class with the fake version. You perform your logic, and then at the bottom, you perform your assertion. And these assertion methods will be unique to each class.

You perform your logic, and then at the bottom, you perform your assertion. And these assertion methods will be unique to each class. So for your notification fake, yeah, you'll see that you have some assertion methods that you can call. All right, so that'll do it.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟