Copy

Codebyjeff Laravel Quick Tip

NOTE: A couple of Quick Tips ago I talked about using Validator classes elsewhere in your code. Coincidentally, Stefan Doorn wrote a post about doing just that. Check it out for a great use case! https://dotdev.co/use-laravel-validator-while-filtering-collections-e4e753d40b99#.twzxi82fv


Hello, Laravel Friends!

You know you should mock services like API calls when you're testing, but that means a whole new set of techniques to learn. Sometimes we *are* in a hurry and need to get things done, not spend a day studying. Fear not! Here's a trick that can help us with that particular problem.

You remember your containers and binding? If you're like me (and maybe you shouldn't be), you may not use the App Container for very much. Here's a reason to consider doing so, particularly for Services.

Imagine we have a `TwitterService` class that does the usual wrapper functionality and has a funcation called `twitterHandleExists($handle)` that returns a boolean. You have been injecting this into your other services where needed, and now you want to test them.

Good testing says that `TwitterService` should have its own tests, but then mocked elsewhere. Which means pulling in mockery and learning how that's all supposed to work - a good thing to do, but perhaps there's no time today? Most of us would just say the heck with it and go ahead and hit Twitter API with every test, trusting that the site doesn't go down much so it just means a slower test.

Instead, let's look at binding. We all learned about this when the Repository Pattern became popular, then it soured a little from overuse when we realized we probably weren't ever going to use it for the purpose it was designed for. Here is a perfect use, however.

The trick is essentially this: you have your actual class, and a copy of it called `TwitterServiceMock` with function `twitterHandleExists($handle)` that always returns "true". What we want to do is to either dynamically bind the class to the interface, or dynamically add the class we want to the App Container. This way, when we are testing our mock object that always returns true will be used.

In your AppServiceProvider's `boot()` function we'll write one of these two bits of code:

$this->app->bind('TwitterService', function(){

    if ($this->app->environment() == 'testing'){
        return new TwitterServiceMock();
    }

    return new TwitterService();
});

puts the appropriate class into the container, which we can then access with `$this->app->make('TwitterService');` (or the shorter `$this->app['TwitterService']` ) anywhere in our code.

Alternatively, we can bind to the Interface like:

$this->app->bind('App\Services\TwitterServiceInterface', function(){

    if ($this->app->environment() == 'testing'){
        return new TwitterServiceMock();
    }

    return new TwitterService();
});

and then type hint the functions when we use Dependency Injection:

public function __construct(TwitterServiceInterface $twitterService){
   // ...
}

This doesn't let you off the hook for further studying Mocks, but it can be a very useful tool.

Hope that helps!

Thanks for reading! If you found this useful, help me spread the word  share on Twitter

Read it Monday, use it by Friday!

Jeff

Copyright © 2016 Jeff Madsen Designs, All rights reserved.


Want to change how you receive these emails?
You can update your preferences or unsubscribe from this list

Email Marketing Powered by Mailchimp