Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

364
Views
PHP Unit Testing - Mock static autoloaded class with Mockery

I want to unit test a wrapper class for the official Segment PHP integration. Therefore I'll have to mock the Segment class with Mockery so there won't be any real API requests.

The Problem

The class to mock consists only of static methods. Because of this I try to mock it like this (with alias):

$segment = Mockery::mock('alias:Segment');

This works, but only if the class isn't autoloaded by composer. If I load it - like I have to for the rest of the app - I'll get the error

Could not load mock Segment, class already exists.

(That makes sense, because the docs state that an aliased class must not be loaded before.)

The question

How can I mock this (evil?) class, but still use it as usual in the rest of my app?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Essentially, you cannot mock classes with static calls.

Static calls always reference exactly the class and method to be called, which is equivalent to pointing to exactly the file and line of code to be executed (if you assume basic autoloading capability is available).

The only way to execute different code is to NOT having included the original class, but to load the mock class code first. It does not matter if you have an alternative code file, or if you are calling eval() by using Mockery. Both ways will work.

But they will also work only one time. You cannot switch back to the original code in a later test, because the class can only be defined once per script run. And not being able to switch implementations (like original vs. mocked vs. another mocked) is the problem here.

The solution, which also was mentioned in the comments: Don't have classes with static methods. Always create instances of classes and call dynamic methods. This way you can easily mock the class, but it requires to create an instance first, and offer a way to inject the class (or at least the mocked class) into the code you want to test.

As a generic pattern I am using this if dependency injection is not available in the project (I have to deal with some legacy stuff at times):

public function __construct(MyClass $class = null) {
    $this->class = $class ?: new MyClass();
}

This way I don't have to inject the class, but I would be able to inject a mock instead of the real class.

For situations where dependency injection is available, the constructor will be a very basic initializer:

public function __construct(MyClass $class) {
    $this->class = $class;
}

This works great if your dependency injection framework is able to do auto wiring (like PHP-DI), and you only have exactly one MyClass, because this will be automatically injected without you having to define anything.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!