Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProxyMock - mock that intercepts calls to existing object #24

Open
MartinMystikJonas opened this issue May 23, 2014 · 8 comments
Open

Comments

@MartinMystikJonas
Copy link

This is feature we just working on. It is not final yet, but I would like to have your input.

Working name for this is ProxyMock.

Main idea is that sometimes you do not want your mock object to mock all calls for some object just intercepts some calls and let everything else pass to some real instance. Basically in test you only care about part of the object behaviour and do not want to be forced to set expects for all calls.

Most useful is this if mocked object has some complex behavior or computation or if call sequence and/or internal state is important for return values.

Creating of proxy mock is simple. Just pass existing instance instead of class/interface name when creating mock:

  class MyObject {
    public function multipleTwo($param) {
      return $param * 2;
    }
    public function plusOne($param) {
      return $param +1;
    }
  }

  $object = new MyObject();
  $mock = $mockista->create($object);

When we set no expects it will just passthrought all calls to original object:

  echo $mock->multipleTwo(10); // => 20
  echo $mock->plusOne(10); // => 11

We can set expect for some calls and return different values:

  $mock->expect('multipleTwo')->andReturn(100);
  echo $mock->multipleTwo(10); // => 100
  echo $mock->plusOne(10); // => 11

Of couse we can set expectations in number of calls as normal

  $mock->expect('multipleTwo')->once();
  echo $mock->multipleTwo(10); // => null
  $mock->assertExpectations();

For case when we want to set expectation but still return value computed by original object, new and* method will be added:

  $mock->expect('multipleTwo')->once()->andPassThrough();
  echo $mock->multipleTwo(10); // => 20
  $mock->assertExpectations();

Of course we can use some fake implementation of original object as well:

class MyDummyObject extends MyObject {
 ... some dummy behaviour
}

$mock = $mockista->create(new MyDummyObject());

So what do you think?

@MartinMystikJonas
Copy link
Author

Pull request for this feature is here #27

@janmarek
Copy link
Owner

I've tried to implement something similar, you can look at it at jm-partial-mocks branch: https://github.com/janmarek/mockista/compare/jm-partial-mocks.

Unfortunately I've realized that it needs to be completely rewritten to pass the last test. Mocking methods called from not mocked method is indeed a useful function and it can be achieved only by inheritance, not composition. So method delegation has to be done by generated code by ClassGenerator.

@MartinMystikJonas
Copy link
Author

But using inheritance you still have to construct whole new object. I think it is bit different use case than proxy mocks. Main motivation here was to only intercept calls to existing, already initalized, objects.

We use this mainly in presenters testing where we create proxy mocks of presenter dependencies. Then we can assert only important calls to these dependencies if we want but do not have to create them on our own.

Partial mocks are good idea too, but they are not so useful in case when mocked object have lot of dependencies.

@jasir
Copy link
Contributor

jasir commented Nov 10, 2014

This should be merged.

@f3l1x
Copy link
Collaborator

f3l1x commented Oct 8, 2015

👍

@MartinMystikJonas Any progress?

@MartinMystikJonas
Copy link
Author

@f3l1x PR is ready #27

We use my fork with this feature

@f3l1x
Copy link
Collaborator

f3l1x commented Mar 13, 2017

@MartinMystikJonas Do you think we can merge it?

@MartinMystikJonas
Copy link
Author

Not sure. We use it in our own fork but I did not update upstream for long time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants