Planning Tweet Command Test0:00
Now that we have made sure that we can purchase a course, our tests are working, but also we've tested this in the last video through the browser, we can now check this off. And this also means the last main to-do, which we have here, is when we want to make sure that an admin can send out a tweet about a release course. And I'm thinking here about a console command where we can trigger it through the console and send out a specific tweet with some specific text about a new course which we have just launched. So let's try to build this. And as always, I want to start here with a test. Since I already know that this will be a console command, I want to make sure that for every command I also have a dedicated test. So this will be a new feature test, and we're going to call it TweetAbout. So the first part will be the name of the command, which we don't have yet, but
I also have a dedicated test. So this will be a new feature test, and we're going to call it TweetAbout. So the first part will be the name of the comment, which we don't have yet, but it will be called TweetAboutCourseRelease command, and then now we are starting with the test. And then we want to make sure it tweets about release for a provided course. Now we're going to think about how are we going to test this. So I'm a big fan of using facades, but also using fake methods of facades. And we have seen some similar approaches here. And here we're going to deal with later with some kind of Twitter client, Twitter class, Twitter facade probably. And what I also want to do is I want to fake this service. So I'm thinking about something like this, Twitter::fake(). So this is very similar to what Laravel does, for example, for the mail system, for the queue system, where we can
I want to fake this service. So I'm thinking about something like this, Twitter fake. So this is very similar to what Laravel does, for example, for the mail system, for the queue system, where we can fake the queue system. But in our case, we want to deal now with some kind of Twitter service. And the beginning of our test, we want to make sure that we fake it so that we don't really send out any tweets. Then, of course, what we also need here in order to test this, we need some kind of Course inside the database. So let's create one, factory. Great, here we go. Let's import the namespace. And then we want to trigger this. And we can do this inside a test by calling the artisan method. And now we're going to call our command. And again, it's called tweetAboutCourseRelease. And we're providing it a class. And we also want to make sure that in the signature of this command, we're going to provide the ID of the Course. So this means there will be some
course release. And we're providing it a class. And we also want to make sure that in the signature of this command, we're going to provide the ID of the course. So this means there will be some kind of courseId, which we provide to our signature of the command. And this will be the ID of the course, which we have just created, because this is also the course, which we want to tweet about. And then at the end here, we also want to make some kind of assertion. And since we're going to switch out the Twitter client with some kind of fake Twitter client, I also think about some custom assertion methods here so that we can do something like level also does with its facade. So I want to call here some assertion. So I want to make sure that a specific tweet was sent with some specific text here. And this will be, I just released. And let's use or write a name of the course. I just released the title of the course.
that a specific tweet was sent with some specific text here. And this will be, I just released. And let's use or write a name of the course. I just released the title of the course. Check it out. And then we are going to provide the link to the course. And let's use the route helper here. pages.courseDetails, I think is the correct route. And here we are also providing the course in order to create this specific link. So let's check it out again. We want to make an assertion that a specific tweet was sent with this text. I just released courseTitle. Check it out. And then on this specific page, I think this looks good. All right. So while we are faking our Twitter system, which we don't have yet, but I already know that I want to work this way. We want to make sure that we have a Course. We call our tweet about CourseRelease Comment. This will be with a specific courseID.
Creating Twitter Facade Alias3:56
but I already know that I want to work this way. We want to make sure that we have a course. We call our tweet about course release comment. This will be with a specific course ID. And then we make sure that we get that a specific tweet was sent. But as always, we're going to run our test and it will tell us where to start. All right. So class Twitter is not found. So this is not given. Let's start here by creating a new class and let's call this TwitterFacade. And also you want to make sure that we extend the BaseFacade like this. And then also inside our config up here, I want to make sure that on the aliases that there is now our Twitter alias for this TwitterFacade. And here we provide the TwitterFacade class. All right. So this means now inside our test, we can see here that we want to use Twitter.
alias for this Twitter facade. And here we provide the Twitter facade class. All right. So this means now inside our test, we can see here that we want to use Twitter. And then our applications should understand that this is now the Twitter facade. All right. Let's run it again. Facade does not implement the getFacadeAccessor method. That's true because every facade needs to implement this method. So we're also going to do this here. We find it here. Yeah. protected function getFacadeAccessor(). And here we are just using a string Twitter. So this means we are telling that when we also need to return this, when someone uses this facade here, we want to make sure that the service which we are using is bind to the alias Twitter inside the service container. And we're going to return here a
Adding Console Command Skeleton5:27
when someone uses this facade here, we want to make sure that the service which we are using is bind to the alias Twitter inside the service container. And we're going to return here a string. All right. Let's run the test again. Call to undefined method Twitter facade fake here. All right. So this means we are now one step further because now this fake method is not given on our Twitter facade. So let's add this here. public static function fake. Let's run the test again. And now we have a different error. CommentNotFoundException. Yeah. So this means we can move on here because now this comment is not given. Let's create it. Create ConsoleCommand. And we're going to call it tweetAboutCourseReleaseComment. And the signature tweet about course release I think is also fine. Let's import this here. Let's run the test again. As always, I really liked that my tests tell me what to do.
Implementing Twitter Fake Assertions6:21
comment. And the signature tweet about course release I think is also fine. Let's import this here. Let's run the test again. As always, I really liked that my tests tell me what to do. InvalidArgumentException. Yeah. So we haven't provided the course ID, which we have to provide here to the signature. So this means we're going to expect here a parameter, which is the ID of a course. Let's run it again. Call to undefined method assertTweetSet. All right. So this is now a different step here because now we are already here at the end where our test does not know what this means because we haven't created this assertTweetSend method. All right. Let's take a look at our Facade again. So we have here our fake method, but we don't do anything here. And what we want to do is we want to swap out the implementation of the real TwitterClient, which we also don't have yet with a fake one. So this looks something like this. There is a self
here. And what we want to do is we want to swap out the implementation of the real Twitter client, which we also don't have yet with a fake one. So this looks something like this. There is a self::swap method on the Facade, which we can use. And here we want to provide now a new TwitterFake instance. Of course, we also don't have this yet, but this is how we want this to work. And this means then after calling this fake method, whenever the Twitter Facade has been used, then it will use not a fake implementation and not the real one. Let's run it. And yeah, this is not given. So now's a good time to create this new class. So this means inside our test directory, I like here to already create a new directory and call this fakes here because we only need this for our tests. And now we're going to create a new class and call it TwitterFake. Let's go back to our Facade here. Let's import this class,
this fakes here because we only need this for our tests. And now we're going to create a new class and call it TwitterFake. Let's go back to our facade here. Let's import this class, which we now have. And now let's try this again. Call to undefined method, assertTweetSent. So the issue is pretty similar to before, but now our application tries to run this method on the TwitterFake instance. And this is exactly what we want to do because this is also the method which we want to create here in this new fake class. So maybe let's start with the function which we're going to need. assertTweetSent. So we're going to provide here the string, which is the content of the tweet. And in the Twitter world, this is called a status. And we're going to return the instance of TwitterFake itself already. And now here, we want to make sure that this text here is already given somewhere. And the idea is with
And we're going to return the instance of TwitterFake itself already. And now here, we want to make sure that this text here is already given somewhere. And the idea is with this TwitterFake class that we're going to store all the tweets that we would have sent in some kind of array. And then we just make sure that a specific string is given. So we're going to use then an assertion from phpunit, assertContains. And then we want to make sure that our status is inside. Yeah, where do we store the tweets? We're probably going to store this in some kind of array, which we're going to call tweets. So let's create this one. Array $tweets. And at the beginning, this is just an empty array. And now what I already know is that we need some kind of function to fill this. And this will be a function called tweet, which we're going to call later inside our comment. And here again, we are providing a string, which is the status of our
function to fill this. And this will be a function called tweet, which we're going to call later inside our comment. And here again, we are providing a string, which is the status of our tweet, the message, the text message, which is inside. And later, we're going to return an array because this is also what the real Twitter API does, returning an array when you try to tweet something specific. And now we want to store inside our tweets array, a new item. And it's the message, which we get through the status. And then for just for debugging, we're going to return here an array similar to what Twitter does. And it just also gives you back the status, which is the text we just tweeted. I think it looks something like this. We're going to see about this later. But I think this now looks good. And here, I think we're going to need to return the instance itself in order to don't see an issue here. All right. So we're going to use a TwitterFake class.
But I think this now looks good. And here, I think we're going to need to return the instance itself in order to don't see an issue here. All right. So we're going to use a TwitterFake class. Then we're going to use some kind of tweet method. So again, this will be the same API as the real Twitter client, where there's also a tweet method. And here, we're not sending any tweets. We're just storing the messages inside this array. And then with this assertTweetSend method, we can check if inside this array is a message which were provided to this assertion. Okay. Let's run this again. And let's see. Field asserting the array contains a specific message. All right. So we don't have this yet. And this is true because we don't send anything inside our command here. So let's try to do this now. Maybe let's also add here a description, a better one. Tweet about a course release. Yeah, I think that's enough. Now here, first, we want to make
Implementing Command Tweet Logic11:21
command here. So let's try to do this now. Maybe let's also add here a description, a better one. Tweet about a course release. Yeah, I think that's enough. Now here, first, we want to make sure that we find the Course for the course_id, which we get through the argument. And let's findOrFail here. I want to fail here because if we don't find the Course, then we definitely don't want to tweet anything out. And then here, we have access to the argument for the signature. And it's called course_id. And then here, we also want to use not a Twitter facade. And we want to use it through the alias. And now, we're calling the tweet method. And now, the text will be very similar to before. Or actually, it should be exactly the same. All right. I think this looks good now. But we will only know if we run the test again. And let's see. Class Commands\Twitter not found. I think what we also need to do here is use now our Twitter facade. I think we can use
good now. But we will only know if we run the test again. And let's see. Class Twitter not found. I think what we also need to do here is use now our Twitter facade. I think we can use it like this. And yeah, finally, we can see a passing test now for the first time. And if we go back to our test, we can see now that we have made sure that when we run a specific command, that we want to make sure that a specific message would have been sent. But since we're faking the Twitter client, it is not being sent.
