Damien Walsh
Damien Walsh

Reputation: 127

how to mock global functions and classes used by another class

I am trying to write a test, and one of my methods makes use of a global function web() which takes a (string) url, and creates and returns new instance of UrlHelper. This gives my app some shortcuts to some helper methods. (Yes DI would be better, but this is in a larvel app...)

The method I'm trying to test, uses this global helper to get the content of the given url and compares it to another string.

Using phpunit, how can i intercept the call to web or the creation of UrlHelper so i can ensure it returns a given response? the code looks a bit like the following

function web($url){
 return new \another\namespace\UrlUtility($url);
}

...

namespace some/namespace;

class checker {
   function compare($url, $content){
       $content = web($url)->content();
       ...logic...
       return $status;
   }
}

The unit test is testing the logic of compare, so i want to get expected content from the web call. I was hoping mocks/stubs would do the trick - but I'm not sure if i can hit this global function or another class which isn't passed in?

Thanks

Upvotes: 7

Views: 10749

Answers (3)

Kolyunya
Kolyunya

Reputation: 6240

  1. Define a nice cohesive interface for your web utility.
  2. Refactor that global function into the class implementing that interface.
  3. Inject the interface into the client classes. You don't need any frameworks for this. Just pass it as a constructor argument manually if you don't have a DI container in your project.
  4. Provide a mock implementation of the interface in the testing environment.

Upvotes: -2

OnIIcE
OnIIcE

Reputation: 871

You can overload the class using Mockery and then change the implementation of the method.

$mock = \Mockery::mock('overload:'.HelperUtil::class);
$mock->shouldReceive('content')->andReturnUsing(function() {
    return 'different content';
});

Upvotes: 8

Beevee
Beevee

Reputation: 198

You can be dirty a re-declare the global function within your namespace in the test, which will take precedence.

Note: it's dirty.

Upvotes: 4

Related Questions