Reputation: 1834
I just created a Manager
that deals with a SuperClass
that is extended all over the code base and registered with some sort of SuperClassManager
(SCM
).
Now I would like to test my Manager
that is aware of only the SuperClass
. I tried to create a concrete SCM
, however, that depends on a third party library and therefore I failed to do that in my jUnit test. Now the option is to mock all instances of this SCM
.
All is good until now, however, when my Manager
deals with the SCM
, it returns children of the SuperClass
that my Manager
does not know or care about. Nevertheless, the identities of these children are vital for my tests (for equality, etc.).
Since I cannot use the concrete SCM
, I have to mock the results of calls to the appropriate functions of the SCM
, however, this means that my tests and (indirectly) my Manager
need to know and care about the children of the SuperClass
.
Checking the code base, there does not seem to be a more appropriate location for my test (that already maintains the appropriate real dependencies).
Is it worth it to introduce unnecessary dependencies for the sake of unit testing?
Update 18/DEC/2012
Here is a simplified version of my problem:
package some.package.declaration;
import some.open.source.framework.TopComponent;
import some.open.source.framework.WindowManager;
/**
* Own source code.
* Knows WindowManager and TopComponent; but no
* direct child of TopComponent.
*/
class TopComponentManager{
/**
*
*/
void efficientlyDoOperationsOnCurrentTopComponents(){
Set<TopComponent> currentTopComponents = get all current TopComponents from WindowManager;
Set<TopComponent> getNeededTopComponents(currentTopComponents);
do some operations on the current TopComponents;
...
...
}
void Set<TopComponent> getNeededTopComponents(Set<TopComponent> givenTopComponents){
Set<TopComponent> neededTopComponents = new HashSet<TopComponent>(givenTopComponents);
disregard and keep some TopComponents based on controls;
return neededTopComponents;
}
}
package some.package.declaration.test; // same project as TopComponentManager
import jmockit;
import some.open.source.framework.TopComponent;
import some.open.source.framework.WindowManager;
import own.source.code.childrenOfTopComponent.ChildTopComponent; // Don't want to; need to introduce package dependencies
import own.source.code.childrenOfTopComponent.AnotherChildTopComponent; // Don't want to; need to introduce package dependencies
class TopComponentManagerTest{
@Tested
TopComponentManager _topComponentManager;
@Mocked
WindowManager _windowManager;
@Mocked
ChildTopComponent _childTopComponent1; //extends TopComponent; unknown to both TopComponentManager and TopComponentManagerTest
@Mocked
AnotherChildTopComponent _childTopComponent2; //extends TopComponent; unknown to both TopComponentManager and TopComponentManagerTest
Set<TopComponent> _currentTopComponents = new HashSet<TopComponent>();
@Before
void setUp() throws Exception {
_currentTopComponents.add(_childTopComponent1);
_currentTopComponents.add(_childTopComponent2);
}
void testgetNeededTopComponents(){
Deencapsulation.invoke(_topComponentManager, "getNeededTopComponents", _currentTopComponents);
new Verifications(){{
verify that only _childTopComponent2 is returned;
}};
}
}
As can be seen, while testing the TopComponentManager, I have to verify the determined necessary elements which are unknown at this package.
Upvotes: 4
Views: 376
Reputation: 1834
I ended up solving this problem by creating a new project that only contained my test class. This test class had dependencies to the TopComponentManager
and all the child TopComponent
s that were spread around the code base. However, the dependencies are not a matter of concern.
With this approach more tests can be implemented within this project that will not create any additional dependencies on production code.
Upvotes: 0
Reputation: 42903
Why not just mock TopComponent
directly?
Example:
@Mocked
TopComponent _childTopComponent1;
Upvotes: 2
Reputation: 15982
Perhaps if you could give use some code, then it would be easier to give you an answer.
Also, how do you call the SuperClassManager
when Manager
is only aware of SuperClass
? Is it a dependency inside the SuperClass
? If that's the case, then SuperClass
has a wrong dependency and you should consider removing this from SuperClass
.
But if your manager is not aware of the SCM
, but only of the SuperClass
, then you should mock the SuperClass
because the test of the Manager
must not be dependent on code of other components and you should not create unnecessary dependencies.
Upvotes: 0
Reputation:
Not sure if that's what your are looking for but Mockito provide a way to return mocks when a method of a mock is called:
SCM scmMock = Mockito.mock(SCM.class, Mockito.RETURNS_MOCKS);
// scmMock.someMethod() will return a mock
Upvotes: 0