arin
arin

Reputation: 1834

Creating Dependencies Only to be able to Unit Test

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

Answers (4)

arin
arin

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 TopComponents 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

Koraktor
Koraktor

Reputation: 42903

Why not just mock TopComponent directly?

Example:

@Mocked
TopComponent _childTopComponent1;

Upvotes: 2

Tom Verelst
Tom Verelst

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

user180100
user180100

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

Related Questions