I have to write unit tests for some classes my group is developing. The classes are fairly simple, and I’m not sure how to best test them.
public class MyObjectRegistry
{
private myDataSetMapper = new MyDataSetMapper();
public boolean StoreObjects(list<MyObject> myObjectList)
{
myDataSetMapper.StoreObjects(myObjectList);
}
}
public class MyDataSetMapper
{
public boolean StoreObjects(list<MyObject> myObjectList)
{
for(MyObject myObj: myObjectList)
{
boolean result = StoreObject(myObj);
}
}
private boolean StoreObject(MyObject myObject)
{
//Store the object in a database
}
}
So my question is how to test the MyObjectRegistry.StoreObjects
and MyDataSetWrapper.StoreObjects
methods since there’s no real logic other than a foreach
loop and calling out to another method.
I’ve looked around the web and found that I think I’m looking at a “facade” class/method, but I’m still unclear on what would I should test/assert in the test method.
3
So unit tests are there to test logic, not plumbing. You don’t have any logic in your (albeit small) example so it dosent need testing.
Generally speaking it should be obvious what needs testing in a method since it does one thing and its name tells you what it does. If that isnt the case you should probably look into breaking your code into smaller components.
1
The problem you are facing is the result of “bad” class design. Specifically MyObjectRegistry was not designed to facilitate unit testing. Luckily, reflection allows you to set private values of classes.
Here is what I would do in your situation:
- Create a mock version of MyObjectRegistry; probably using a List, a Map, or, perhaps, a Map of List ojects.
- At the start of your junit test (perhaps in class setup) create a MyObjectRegistry instance then set the myDataSetMapper member to the mock version of the MyDataSetMapper class.
- Call the storeObjects method then check to see that the values which were passed to the storeObjects method were added to the mocked MyObjectRegistry object.
Assuming that the database access code in not inside the MyDataSetMapper.storeObject() method, do the same thing for MyDataSetMapper with a mocked data access object.
The problem is that MyObjectRegistry
creates a new MyDataSetMapper
, instead of having that dependency injected. The appearence of “new” creates a hard, compile-time dependency on MyDataSetMapper
. There are two ways to go:
-
Use a reflection utility (Like ReflectionTestUtils) to forcibly set that variable to a mock instance of MyDataSetMapper. Yuck!
-
Change the class so that instead of instantiating
MyDataSetMapper
, it gets injected as a dependency instead:public MyObjectRegistry(MyDataSetMapper mapper) {
this.myDataSetMapper = mapper;
}
Now you can instantiate the registry with an injected mock instance, and you’re testing the unit under test (the registry object) and not the MyDataSetMapper.
- If MyDataSetMapper talks directly to the database, then there’s no point in testing it in isolation, since it’s by nature an integration object. You can test that out in integration tests, or just by running and exercising the application.