2

I have this method:

public function getLocale()
    {
        $languageId = $this->_user->language->id;
        $page = Wire::getModule('myModule')->getPage($languageId);
        $locale = $page->locale;

        if (!!$locale) {
            return $locale;
        }

        // fallback to browser's locale
        $browserLocale = new SBD_Language();
        $locale = $browserLocale->getLanguageLocale('_');

        return $locale;
    }

Now I want to write a test for it, but I get this error: Trying to get property of non-object which is caused by Wire::getModule('myModule').

So I'd like to override the Wire::getModule response with phpunit. I just don't know how to do that.

So far I have created a mock over the class in which the method getLocale is placed and that is all working fine but how would I tell that mock class that it should actually call a mock of the Wire class?

  • You can't mock static methods. – Jack hardcastle Mar 17 '17 at 09:49
  • So can I test this method than? –  Mar 17 '17 at 09:51
  • You could intercept the call to the static method if you really wish to test it.. So have a proxy class that calls the static method itself, you can mock that proxy class `$this->callProxy($something)` can be mocked, and the `callProxy($something)` method could simply call the static method with `$something` – Jack hardcastle Mar 17 '17 at 09:53
  • You can use `Phake` test library that support [Mock static method](http://phake.readthedocs.io/en/2.1/mocking-statics.html) – Matteo Mar 17 '17 at 09:54
  • @Jackhardcastle How can I use a proxy to intercept the Wire::getModule call? Do you have an example or any documentation about it? –  Mar 17 '17 at 10:07
  • this is one of the reasons why static methods are bad. They introduce dependencies like this one that you can't easily mock. The `new SBO_Language()` line might give you problems too, for similar reasons. In that case you can at least fix the issue by using dependency injection – GordonM Mar 17 '17 at 10:16
  • 2
    Ideally you should refactor this method and not call global functions from it. I would redefine it like this: `public function getLocale($page)` then you can pass a mock page object to it from the test class. – laurent Mar 17 '17 at 10:17
  • Is processwire bootstrapped there? What about `wire('modules')->get('myModule')-> ...`? – stewo Mar 18 '17 at 01:16

1 Answers1

1

You can kind of mock static methods by proxying the call to the static method, as such

class StaticClass
{
    static function myStaticFunction($param)
    {
        // do something with $param...
    }
}

class ProxyClass
{
    static function myStaticFunction($param)
    {
        StaticClass::myStaticFunction($param);
    }
}

class Caller
{
    // StaticClass::myStaticFunction($param);
    (new ProxyClass())->myStaticFunction($param); 
    // the above would need injecting to mock correctly
}

class Test
{
    $this->mockStaticClass = \Phake::mock(ProxyClass::class);
    \Phake::verify($this->mockStaticClass)->myStaticMethod($param);
}

That example is with Phake, but it should work with PHPUnit the same way.

Jack hardcastle
  • 2,748
  • 4
  • 22
  • 40