-
-
Notifications
You must be signed in to change notification settings - Fork 313
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
Add qualifier to disambiguate injection #3
Conversation
Add qualifier element to Mock annotation to disambiguate injection of multiple mocks of the same type.
Keep it simple is a good idea. It needs to stay intuitive. I think that when a qualifier is used, it should match or throw an exception. I can't see cases where one would like a qualifier set but unused. Also, maybe the qualifier should be called "fieldName" to be obvious (does it still fit if we allow to inject on setters?) The would bring the following rules:
WDYT? |
Yes, I like that. "fieldName" is a more directly obvious name. Treating an unmatched fieldName as an error is better for avoiding behaviour that is hard to debug. Separately explaining the behaviour for qualified and unqualified injection makes it clearer. I'll make those changes. To clarify the case where two mocks can be assigned to the same field - in the first draft, if a qualified mock and an unqualified mock can be assigned to the same field, the qualified mock is assigned. Sounds like you want this to be an error, and I think I now agree, i.e. if two mocks, whether qualified or unqualified or a combination, can be assigned to the same field, return an error. Seems simpler that way. Wherever there is a possibility to assign two mocks to the same field, it's an error. |
It would want that everything qualified be set first. And then the unqualified ones. So if you have two fields with the same type, you only have to qualify only one. The one thing I would like to avoid is ambiguity. I don't want a field to be assigned randomly to the first matching mock the algorithm found. |
Ah, OK, cool. "Ignoring all fields and mocks matched by field name" is the vital piece I didn't fully grasp. When looking for places to assign unqualified mocks we exclude any fields already assigned a qualified mock. |
Exactly On 3 November 2013 18:03, Alistair Todd notifications@github.com wrote:
|
If it feels unclear, feel free to add precisions On 3 November 2013 18:57, Henri Tremblay henri.tremblay@gmail.com wrote:
|
Change to qualifier element to fieldName as a more directly obvious and explicit name for the role of that element.
Refactor injection routine to ensure deterministic behaviour and rejection of ambiguous input. Mocks with fieldname qualifiers are injected first. Duplicate qualifiers and unsatisfied qualifiers are errors. Unqualified mocks are not injected where a qualified mock was assigned.
Created a new pull request for an improved solution. This one can be closed. |
Hello,
I've been going around in circles debating the right way to do the injection. In the end I've scrapped most of the ideas I had, aiming at simplicity.
I had favoured injection by name, but I think your decision to go for injection by type was a good one. Whether by name or by type, eventually you run into some odd cases that require special treatment, but for everything else injection by type allows a clean and simple solution that requires minimal configuration by users, is predictable and unsurprising, and efficient.
Your choice of policy for the injection is actually quite convincing and creates the simplicity and consistency:
The biggest problem I have with it is the last line, because it disallows using a different mock for each of two fields with the same type.
The simplest way I can see to get around this is to allow an optional "qualifier" element in the Mock annotation, to identify the target field for the injection.
To implement it without making a mess of deeply nested conditionals, I've reorganised the code into some new classes.
First I've pulled your original injection code into a new Injector class. The first real change in the code is that instead of passing a list of mock Objects, we now pass a list of a new Injection class, which holds the mock Object and Mock annotation that describes it.
When we come to injectMocksOnClass, we enlist another new type, InjectionTarget, just to keep things clean.
When checking each mock to see if it can be assigned to the field, we have a slight variation to account for the qualifier:-
I've added tests for these few cases: Qualifiers distinguish two fields of the same type; A qualified mock displaces an unqualified mock; Duplicate qualifiers on the same type are rejected.
The original injection policy is still true, and all the previous behaviour is preserved, but we add one extra line at the end to clarify what we mean where the first line says "If a mock can be assigned to a field":-
For your consideration!
Al