5

I would like to know if I can mock a super class constructors call and its super() calls.

For example, I have the following classes

class A
{
    A(..)
    {
        super(..)
    }
}   

class B extends A
{
    B(C c)
    {
        super(c)
    }
}

So, I am planning to unit test some methods in class B, but when creating an instance it does call the super class constructors making it tough to write unit tests. So, how can I mock all the super class constructor calls. Also I would like to mock few methods in class A so that it does return few values as I need.

Thanks!!

Rishi
  • 1,331
  • 4
  • 13
  • 16
  • 7
    What *exactly* is making it hard to test B? The fact that it calls superclass constructors isn't *inherently* problematic. You should be trying to mock *dependencies*, not behaviour of the object itself. – Jon Skeet May 02 '12 at 20:43
  • I discuss [suppressing ctors using PowerMock with EasyMock in this blog post](http://buckybits.blogspot.com/2011/11/testing-singletons-and-static-classes.html), I don't have a Mockito version. It's not clear if you want to eliminate the ctor or replace it, though. – Dave Newton May 02 '12 at 20:47
  • 1
    @Jon Skeet. yes I do understand that but in order to achieve that it's lot complex and starts multiple threads in the background invoking many external dependencies which aren't needed for my unit test. – Rishi May 02 '12 at 21:27
  • 4
    Then you should be injecting those dependencies, not creating them in the superconstructor. That's the point. – Louis Wasserman May 02 '12 at 22:00

3 Answers3

1

You could use PowerMock library. It is really a lifesaver when you need to accomplish things like yours. https://github.com/powermock/powermock/wiki/Suppress-Unwanted-Behavior

toddcscar
  • 1,115
  • 9
  • 12
michael nesterenko
  • 14,222
  • 25
  • 114
  • 182
  • 1
    I wasn't aware of that part of the PowerMock library. I still think it points to a "smell" but just because something stinks doesn't mean you have the ability to actually clean it. – jhericks May 03 '12 at 20:20
1

Mocking a constructor is a very bad idea. Doing so is circumventing behavior that will happen in production. This is why doing work in the constructor, such as starting threads and invoking external dependencies, is a design flaw.

Can you honestly say that the work performed in the constructor has no effect on the behavior you're trying to test? If the answer is no, you run the risk of writing a test that will pass in a test environment, but fail in production. If the answer is yes, that is a plain case for moving that "work" outside the constructor. Another alternative is to move the behavior you're trying to test to another class (maybe it's own).

This is even more true if you're using a DI framework like Guice (which I assume because you tagged it that way).

Ryan Nelson
  • 4,466
  • 5
  • 29
  • 45
0

The short answer to your question is "not exactly." You can't 'mock' a constructor, let alone a super. Also mocking super.anyMethod is difficult or impossible with mocking frameworks I'm familiar with. Powermock does allow you to suppress super constructors and problematic methods, which isn't quite the same as mocking them, but could help.

When B extends A, it is of course completely coupled with A. That's not a problem per se but it can be and it looks like it is here. Instead of having B extend A, try having B contain an A instead (and perhaps implement the same interface if necessary). Then you can inject a mock A and delegate all of the calls that you want. That would be much easier to unit test, no?

It's one of the benefits of test driven development that you discover these things in your design during testing.

jhericks
  • 5,833
  • 6
  • 40
  • 60
  • See above re: PowerMock. Regardless of whether it's a good idea or not, replacing a constructor at runtime is possible. – Chris Smowton Jul 07 '16 at 11:34