Allow delayed mock object registration #191

Closed
lstrojny opened this Issue Mar 10, 2011 · 7 comments

Comments

4 participants
@lstrojny
Contributor

lstrojny commented Mar 10, 2011

For more complicated corner cases (like mocking stream wrappers) there should be a way to register mock objects in a delayed fashion. Use case is:

  • stream_wrapper_register() only takes classes and not objects itself. Therefore we register a class with the current test case instance as a composite.
  • When the wrapper is called, we register the actual mock object instance with the case

Patch to add support for PHPUnit_Framework_TestCase::registerMock can be found here: https://gist.github.com/863812

Example stream wrapper mock can be found here: https://gist.github.com/862553

@whatthejeff

This comment has been minimized.

Show comment Hide comment
@whatthejeff

whatthejeff Mar 10, 2011

Contributor

Forgive me if I've misunderstood, but can't you just use PHPUnit_Framework_TestCase::getMockClass() for stream_wrapper_register?

Contributor

whatthejeff commented Mar 10, 2011

Forgive me if I've misunderstood, but can't you just use PHPUnit_Framework_TestCase::getMockClass() for stream_wrapper_register?

@lstrojny

This comment has been minimized.

Show comment Hide comment
@lstrojny

lstrojny Mar 10, 2011

Contributor

I could, except that getMockClass won’t register itself on instantiation with the testcase. So __phpunit_verify() won’t be called on the stream wrapper mock object. The reason is, that PHP internally creates a stream wrapper instance for each fopen() call for the specific wrapper. Except if I missunderstood how getMockClass() works internally, but I could not find any pointer that it will register its instances in the testcase.

Contributor

lstrojny commented Mar 10, 2011

I could, except that getMockClass won’t register itself on instantiation with the testcase. So __phpunit_verify() won’t be called on the stream wrapper mock object. The reason is, that PHP internally creates a stream wrapper instance for each fopen() call for the specific wrapper. Except if I missunderstood how getMockClass() works internally, but I could not find any pointer that it will register its instances in the testcase.

@whatthejeff

This comment has been minimized.

Show comment Hide comment
@whatthejeff

whatthejeff Mar 10, 2011

Contributor

Oh, I understand. You want some sort of dependency injection for stream_wrapper_register(). My instinct is that you should test that your stream wrapper class works correctly in isolation. Testing that PHP is internally invoking the correct methods with a mock isn't really a unit test, right?

Contributor

whatthejeff commented Mar 10, 2011

Oh, I understand. You want some sort of dependency injection for stream_wrapper_register(). My instinct is that you should test that your stream wrapper class works correctly in isolation. Testing that PHP is internally invoking the correct methods with a mock isn't really a unit test, right?

@lstrojny

This comment has been minimized.

Show comment Hide comment
@lstrojny

lstrojny Mar 10, 2011

Contributor

Thanks for the hint, but I don’t need to test my stream wrapper but a component, using stream wrappers.

Contributor

lstrojny commented Mar 10, 2011

Thanks for the hint, but I don’t need to test my stream wrapper but a component, using stream wrappers.

@whatthejeff

This comment has been minimized.

Show comment Hide comment
@whatthejeff

whatthejeff Mar 10, 2011

Contributor

Yeah, I figured that's what you're trying to do. What I'm saying is that you don't really need a mock. Mocks are for verifying expectations about which methods are called and how they are called.

What you really want is a stub. Just make a class that implements the appropriate interface but always returns some canned response. PHPUnit kind of combines these concepts, but you can easily create a stub class yourself without any assistance from PHPUnit.

Contributor

whatthejeff commented Mar 10, 2011

Yeah, I figured that's what you're trying to do. What I'm saying is that you don't really need a mock. Mocks are for verifying expectations about which methods are called and how they are called.

What you really want is a stub. Just make a class that implements the appropriate interface but always returns some canned response. PHPUnit kind of combines these concepts, but you can easily create a stub class yourself without any assistance from PHPUnit.

@Darhazer

This comment has been minimized.

Show comment Hide comment
@Darhazer

Darhazer Sep 3, 2015

👍 for registering additional mocks.

I'm creating DSLs for creating the stubs&mocks for complex methods. Basically my mock objects are created by builders. The problem is that in this way they are not registered with the test. I have to pass the test instance to the builder just to be used to get the mock objects - I cannot pass neither PHPUnit_Framework_MockObject_Generator (as it doesn't have reference to the test), nor PHPUnit_Framework_MockObject_MockBuilder (it has, but it requires the class name) - so I was going to propose registerMockObject and found this thread.

Furthermore, when mocks are created outside of the test, like in my builders, expectations set on the method parameters work (as they are verified at the time of the call), and the only thing that doen't work are the ->expects() calls - as they are never verified. This makes for inconsistent behavior and hard to debug tests ;)

Darhazer commented Sep 3, 2015

👍 for registering additional mocks.

I'm creating DSLs for creating the stubs&mocks for complex methods. Basically my mock objects are created by builders. The problem is that in this way they are not registered with the test. I have to pass the test instance to the builder just to be used to get the mock objects - I cannot pass neither PHPUnit_Framework_MockObject_Generator (as it doesn't have reference to the test), nor PHPUnit_Framework_MockObject_MockBuilder (it has, but it requires the class name) - so I was going to propose registerMockObject and found this thread.

Furthermore, when mocks are created outside of the test, like in my builders, expectations set on the method parameters work (as they are verified at the time of the call), and the only thing that doen't work are the ->expects() calls - as they are never verified. This makes for inconsistent behavior and hard to debug tests ;)

@sebastianbergmann

This comment has been minimized.

Show comment Hide comment
@sebastianbergmann

sebastianbergmann Oct 2, 2015

Owner

Dear contributor,

let me start by apologizing for not commenting and/or working on the issue you have reported or merging the pull request you have sent sooner.

PHPUnit 5.0 was released today. And today I am closing all open bug reports and pull requests for PHPUnit and its dependencies that I maintain. Please do not interpret the closing of this ticket as an insult or a lack of interest in your problem. I am sorry for any inconvenience this may cause.

If the topic of this ticket is still relevant then please open a new ticket or send a new pull request. If your ticket or pull request is about a defect then please check whether the issue still exists in PHPUnit 4.8 (which will received bug fixes until August 2016). If your ticket or pull request is about a new feature then please port your patch PHPUnit 5.0 before sending a new pull request.

I hope that today's extreme backlog grooming will allow me to respond to bug reports and pull requests in a more timely manner in the future.

Thank you for your understanding,
Sebastian

Owner

sebastianbergmann commented Oct 2, 2015

Dear contributor,

let me start by apologizing for not commenting and/or working on the issue you have reported or merging the pull request you have sent sooner.

PHPUnit 5.0 was released today. And today I am closing all open bug reports and pull requests for PHPUnit and its dependencies that I maintain. Please do not interpret the closing of this ticket as an insult or a lack of interest in your problem. I am sorry for any inconvenience this may cause.

If the topic of this ticket is still relevant then please open a new ticket or send a new pull request. If your ticket or pull request is about a defect then please check whether the issue still exists in PHPUnit 4.8 (which will received bug fixes until August 2016). If your ticket or pull request is about a new feature then please port your patch PHPUnit 5.0 before sending a new pull request.

I hope that today's extreme backlog grooming will allow me to respond to bug reports and pull requests in a more timely manner in the future.

Thank you for your understanding,
Sebastian

@sebastianbergmann sebastianbergmann locked and limited conversation to collaborators Oct 2, 2015

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.