-
Notifications
You must be signed in to change notification settings - Fork 1
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
Mocking Library #219
Comments
ReadabilityPlease add some formatting, especially for sourcecode. QuestionsWhere does
QualityThis cannot be a real-life example:
...as DetailsPlease also go into some more detail about the mocking API - what about expecting method arguments? What about member access mocking? How can I make the mock throw exceptions? ... |
Readability
Ok, updated. Questions
$mockery= new Mockery(); //updated Quality
Typo. The method is called "returns". Fixed Details
I have created an introductory tutorial how to use the library. (http://experiments.xp-forge.net/xml/view?arena,mocks,INTRODUCTION.txt) |
Can you add the tutorial to this RFC? The experiments checkout no longer exists as central repository here on GitHub and this link will most probably lead to nowhere in the future. Sorry for being pedantic about this, but we want to keep all the necessary information in the RFC repository to be able to look back at our decisions in their entirety in the future. Thanks for understanding! |
No problem. I'd be glad to upload it. I just wasn't sure where to put it? Comment? Wiki? As file at /rfc/219/tutorial.txt? |
Why not add it to the functionality section - or alternatively, as apidoc for |
Ok, added it to functionality. As I said, it's written as an introductory tutorial. The style might not be appropriate for a RFC ;) |
You can find the pull request issue here: xp-framework/xp-framework#83 |
+1 for this RFC. I'd propose to target 5.8.4 with this. |
+0.9, I'm not happy with |
How about |
MockRepository sounds good, @kiesel ? |
Yap, +1. |
OK, set status to accepted. @iigorr, can you update this RFC with the new name, then update the pull request accordingly? We're ready to go then! |
Ok, done. |
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
# See xp-framework/rfc#219 # Implementation in pull request #83
Updated to work w/ current XP Framework releases: |
Scope of Change
A mocking framework will be added to the unittest API.
Rationale
Easily mock interfaces and verify expected behaviour similar to EasyMock (Java), Rhino Mocks (.Net) and many other mocking frameworks.
Functionality
A new namespace
unittest.mock
is introduced containing everything that enables mock functionallity.Step-by-step approach
The mock library is still under development and does not yet implement all the features grown-up mocking frameworks do. So here is a feature list and a list of things that are not yet implemented (in order of importance).
Implemented:
Not implemented
Usage:
Creating a Mock
Consider service MyService that depends on an IContext which let's you check permissions and read some data:
Now if we want to test the MyService class we have to construct an instance. Probably we would even write a unit test to verify that the construction works:
To create a MyService instance we need an IContext, but in this case it is absolutely irrelevant what the context is, so we just pass null.
When it comes to testing the readContextData method, this won't work as we need a working context.
So we need to initialize an actual IContext. However we might have no concrete class which implements IContext and is easy to instantiate, i.e. without resolving other dependencies like connecting to databases/LDAPs, reading ini-files, configuring stuff etc.
Here is where mocks come into play. We just tell the mock repository to create an object which implements the IContext interface.
Return Values
By default each method of a mocked object returns null. However we might need the dependent object to return actual stuff.
For example to completely test the method getSecretStuff, we need to check two cases.
1)
$this->context->hasPermission("rt=foo,rn=bar") returns TRUE;
2)
$this->context->hasPermission("rt=foo,rn=bar") returns FALSE;
To accomplish that we just tell the context to return the value we want it to.
So now we can write the following test:
To test the exception case (no permissions) we use the following test:
Repetitions
Note that the defintion of the return value is only valid for one call
Thus if you expect that hasPermission is called twice, you need to define the return values for both calls, i.e.
A third call to hasPermission would again yield null.
If you want the same value to be returned a specific number of times you can use ->repeat($numOfRepetions) or ->repeatAny() to repeat the same value permanently.
Argument Matching
When methods have a wide range of input values, it might be difficult to define all expectations. Just imagine if getSecretStuff would check 10 different permissions. We would have to specify an expectation for each of them. For such cases there is a generic argument matching mechanism.
We can use
Arg::any()
if the argument is irrelevant.If specific argument matching rules are required, we may implement an own argument matching class. This class has to implement the
IArgumentMatching
interface.The object is passed as a parameter:
Record/Replay/Verfiy
Now about that $mockRepo->replayAll() call. This is part of the Record/Replay/Verfiy paradigm, that is used for the mocking framework. In the Record phase you tell your mocks how they should behave. With replayAll you activate the Replay Phase. Now when you call methods on your mocks they will actually return the stuff you have recorded. In Verification phase you check whether your recorded expectations are fulfilled.
See http://ayende.com/Blog/archive/2007/12/26/The-RecordReplayVerify-model.aspx
Behavior verification
The verification of a mock is just a check, that ensures that all the calls that were defined in the recording phase are also performed in the replay phase.
You can use
$mock->_verifyMock()
to verify a single mock, or$mockRepo->verifyAll()
to verify all mocks of a mock repository.Example:
Suppose you want to write a test, that ensures that, no matter what, hasPermissions is called when you call getSecretStuff():
If hasPermissions is not called in the above test, then a ExpectationViolationException is thrown, saying "Expectation not met for 'hasPermission'. expected#: 1 called#: 0"
Property Behavior (State Verification)
Somethimes you have properties, that you expect to be set after a test run. The mock library provides a special mode for properties called "Property Behavior". It may be applied to properties that provide a getter and a setter method.
E.g.
This applies only to methods starting with "get" and "set".
Security considerations
n/a
Speed impact
Unittests will run faster if simple mocks are used instead of complex instantiation of dependency objects.
Dependencies
n/a
Related documents
The text was updated successfully, but these errors were encountered: