easymock/easymock — pull request #4 by Todderz (2013-11-08 16:11:15+00:00)
Title: Qualified injection

Here's an improved injection routine for consideration.

Attempting to:
* Ensure predictable deterministic injection
* Fail sooner rather than later
* Minimise looping through test subject fields
* Factor responsibilities into focussed classes and avoid deeply nested code

Implementing the following rules:

* Static and final fields are ignored
* If two mocks have the same field name, return an error
* If a mock has a field name and no matching field is found, return an error
* Then, ignoring all fields and mocks matched by field name
* If a mock without field name can be assigned to a field, do it. The same mock can be assigned more than once
* If no mock can be assigned to a field, skip the field silently
* If the mock cannot be assigned to any field, skip the mock silently
* If two mocks can be assigned to the same field, return an error

Noting that
* Fields are searched recursively on the superclasses
* Qualified mocks are assigned to the matching field name in any test subject, ie may be more than once

Summary of changes:
* Added optional fieldName qualifier in @mock annotation
* Extract injection routine to Injector.java
* Introduced InjectionPlan.java to manage details of qualified and unqualified mocks, and test subject fields, so that the routine for scanning annotations and creating mocks is unaffected by fieldname qualifiers. Also allows duplicate fieldname qualifiers to be detected during the annotation scanning phase.
* Injecting mocks on the testsubject classes now proceeds in two phases; Inject qualified mocks by name, then inject unqualified mocks by type. This requires removing a testsubject field from the available fields when a qualified mock is assigned, so that unqualified mocks can not be assigned to the same field.
* After having performed all possible injections to all testsubjects and their superclasses, check for any qualified mocks that were unsatisfied. Doing this only after we've inspected all testsubjects, and allowing that qualified mocks may potentially be injected more than once, means that we have to mark a qualified mock as having been matched when we assign it, so that any unmatched ones can be identified at the end.
* Expanded unit tests to cover the new rule set

There is an asymmetry between injecting qualified mocks and unqualified mocks, in that for qualified mocks it is better to iterate over the mocks and find fields where there may be assigned, but for unqualified mocks it is better to iterate over the fields and find mocks that may be assigned. There is also a temporal relationship between the two phases, because assigning a qualified mock to a field removes that field from the potential assignment targets for the unqualified mocks.

I've tried to find an acceptable compromise to these competing factors in the injectMocksOnClass method in Injector.java, but it is an aspect on which I would particularly welcome feedback and suggestions.

I try to follow the style of the original as much as possible but I have deliberately diverged in the naming style for the unit tests in EasyMockAnnotationsTest, in order to more clearly express the intention of the different cases.