5

Lets say I have a method:

someMethod(X anObject)

Where X is a type of object that is extremely complex. By this I mean it is not something one can easily instantiate on the fly. I need to somehow unit test someMethod, but I cannot so simply create an X object to put in as parameters.

So I first think to try and mock the object, but the problem I run in to is the someMethod function calls many methods of anObject, meaning this X object that is being mocked has a latge amount of functions that need to be called, and thus need to be mock-expected. To make things worse, these X object methods being called return more X objects, meaning I have to mock objects, to expect mock method calls, to return more mock objects.

Regarding this scenario I have a few questions, as I'm new to the concept of unit testing:

  1. The lengthy unit test method aside, I find my unit test to not only be testing as to whether a method works or not, but also specifying the implementation (because I'm basically specifying most of the code that is being called in the method itself with the mock-expects). Is this a problem (mostly to the concept of unit testing itself)?
  2. Is there any way to get around this, even if only to make my unit test methods be a lot less verbose and more maintainable?
  3. I thought about taking a serialized X object from somewhere else, saving that, and then whenever I call my unit test method, I would unserialize my X object and run that as parameters. This is just some random idea I thought of the top of my head; does anyone actually do this?

In case anyone is wondering what exactly I'm doing, I'm using the IDebugContextListener interface to grab debugging information regarding data on a stackframe at a given step on the java debugger. The "X" that I am referring to are objects that are defined by the interface here, including objects such as IValue, IVariable, and IStackframe. All these variables are provided to me by the Java debugger during runtime.

KWJ2104
  • 1,959
  • 6
  • 38
  • 53

2 Answers2

6

The fact that you have this difficulty is a symptom of a design problem. When something is hard to test, refactor until it isn't hard to test.

If one object needs to call too many methods of another, then encapsulation is poor, and responsibilities are poorly placed. Presumably, the Single Responsibility Principle is not being followed. If code calls methods that return objects, and must call methods on those in turn, then the Law of Demeter is not being followed.

Steve Jorgensen
  • 11,725
  • 1
  • 33
  • 43
  • Thanks for the response; let me explain a bit more about my object. I have a parameter X, and a method parseX(X), whose only purpose is to parse data inside of X in a certain fashion to be returned. X is complex, and thus requires a lot of method calls, but my function is there only for one responsibility. As for the law of demeter, an IStackFrame object (the X) has IVariables, which have IValues, which need to call sendMessage() to return more IValues, which need to call toString() to get a usable string representing data (5 lines of code). Are more methods really necessary (for 1 liners)? – KWJ2104 Aug 06 '12 at 05:58
  • in the sense that you -can- make your test work without them, extra methods are not necessary. You can create mock objects to be returned, and then mock methods that return those. It just sounds like it's going to be ugly, hard to read, and hard to maintained. In order to make the code more test-friendly, you might want the extra methods. In making that change, other beneficial changes might become obvious, and those might involve factoring out other methods. – Steve Jorgensen Aug 06 '12 at 06:58
0

Your pain comes from the fact, that your method does not comply with the Single Responsibility Principle. Your method does a lot of things with X -- and X also sounds a too comlex. This makes testing very hard -- even with mocking.

Break your method down into manageble chunks, that only do one thing each.

Morten
  • 3,778
  • 2
  • 25
  • 45