Skip to content
This repository has been archived by the owner on Aug 24, 2023. It is now read-only.

Allows mocks to inherit public methods from other objects #2

Closed

Conversation

lukeraymonddowning
Copy link
Member

@lukeraymonddowning lukeraymonddowning commented May 18, 2021

Hey!

So, this is one that I find super useful but completely understand if you're not a fan. Usually in larger projects, a mocked interface might have multiple public methods that get called in a feature test. You're only interested in testing one of those methods, but still need to provide a fallback for the other methods.

You might think "that's a partial mock", but I beg to differ because the partial mock might still be doing too much and may still require you to mock the methods/dependencies out.

This PR adds the idea of inheriting public class methods for a mock. You pass it a class, and it will look up its public methods and defer to those if no hard expectation has been set.

Example

First of all, we create an object. It doesn't have to implement anything, but it can if we want to force it to have all of the methods of the interface we're testing.

class BackupClass implements SomeInterface {
    public function get() {
        return 'Hello World';
    }

    public function post() {
        return 'Foo Bar';
    }
}

Now we write our test. We can call methods without using expect, and it will use the method call from the inherited class instead.

$mock = mock(Http::class)->inherit(new BackupClass);

expect($mock->post('get'))->toBe('Hello World');

However, if we use an extend call, it will opt for our overridden version:

$mock = mock(Http::class)
    ->inherit(new BackupClass)
    ->extend(post: fn() => "Hey Nuno!");

expect($mock->post('get'))->toBe('Hey Nuno!');

This gets even more powerful in feature tests, where other methods on the interface might be being called, but you're not interested in testing them at this moment.

$mock = mock(Http::class)
    ->inherit(new BackupClass)
    ->extend(post: fn() => "Hey Nuno!");

$this->swap(Http:class, $mock);

expect(someFeatureThatCallsGetButReturnsPost())->toBe('Hey Nuno!');

This implementation also allows you to provide multiple inherited classes, so you could mix and match methods together based on the use case required for the given test.

Let me know what you think. Hope you're having a good week!

@nunomaduro nunomaduro closed this Jun 10, 2021
@nunomaduro
Copy link
Member

Sorry - I don't see myself using this. Maybe in the future I will re-consider.

Don't hesitate on discussing ideas with the team before implementing them.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
2 participants