9

For unit testing purposes I'm trying to write a mock object of a class with no constructors.

Is this even possible in Java, of is the class simply not extensible?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Ben S
  • 68,394
  • 30
  • 171
  • 212
  • 2
    The question was can it be mocked, not can it be subclassed, given the accepted answer, perhaps you should change the question if that is what you meant? – Yishai Jun 17 '09 at 14:38
  • My questions clearly asks about extensibility. It only mentions mocking as the reason for wishing for this extensibility. – Ben S Jun 17 '09 at 18:08

7 Answers7

21

A class with no constructors has an implicit public no-argument constructor and yes, as long as it's not final, it can be sub-classed.

If the class has only private constructors then no, it can't.

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
Steve Reed
  • 2,481
  • 2
  • 20
  • 20
  • The class in question has only private constructors, including the no-argument one, so I guess I'm just out of luck. – Ben S Jun 17 '09 at 01:05
  • Looks like that class isnt very friendly in terms of testing. You really should be using interfaces rather than concerete types... – mP. Jun 17 '09 at 01:19
  • 1
    So then you're testing a singleton? This always turns out to be a pain in the butt. – matt b Jun 17 '09 at 01:44
  • If the class has interfaces then you can mock the interfaces.You could also work around a final class creating a new class that implements the interfaces and encapsulates a copy of the final class to be extended. – Brian Reiter Jun 17 '09 at 03:28
  • Yes, the object I'm trying to mock is a singleton who's only inheritance comes from Object and has no interfaces... – Ben S Jun 17 '09 at 12:07
  • Technically inner/nested classes can use private members of the enclosing class and it can extend it even if it only have private constructors. However, I am guess this won't help the OP as this assumes you can modify the source of the original class, in which case he would just make the constructor non-private. – Peter Lawrey Jun 17 '09 at 20:14
3

Question has been answered, but to add a comment. This is often a good time to propose that code be written to be somewhat testable.

Don't be a pain about it, research what it takes (probably Dependency Injection at least), learn about writing mocks and propose a reasonable set of guidelines that will allow classes to be more useful.

We just had to re-write a bunch of singletons to use DI instead because singletons are notoriously hard to mock.

This may not go over well, but some level of coding for testability is standard in most professional shops.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • The class I was looking to mock was a Blackberry class which I have no control over. – Ben S Dec 08 '09 at 16:51
  • You make a good point (assuming one is mocking code that they can change), but this probably should have been entered as a comment instead of an answer. – hotshot309 Nov 17 '12 at 03:36
  • I agree but the inability to separate text into paragraphs in comments often leaves me frusterated, but these days (three years later) I think I would have done exaclty that--live and learn. – Bill K Nov 19 '12 at 16:59
3

Yes, you can mock the object, although it may not be possible to subclass it (certainly not without getting very intimate with the class loader, anyway). Here is how you do it with JMock.

Mocking in this fashion allows you to keep the type, without subclassing though it will probably quite hard to impossible to tease out only certain behavior. So this method is appropriate for testing classes that use this class, not for testing the class itself.

If you actually have access to the source code of the class, you could implement an inner class which allows you to extend it, although if you could do that, you could just make one of the constructors package private as well.

There are also dynamic languages which will allow you to do the subclassing, and implement a Java interface which the Java code can interact with, but I'm not that familiar with the details.

Yishai
  • 90,445
  • 31
  • 189
  • 263
2

If java class doesn't have any defined constructors then there is no problem for you. The problems will be if class will have any constructors defined and all of them will be invisible for you (private).

okutane
  • 13,754
  • 10
  • 59
  • 67
2

You can change the visibility modifiers via reflection. Here is an article listing how.

javamonkey79
  • 17,443
  • 36
  • 114
  • 172
1

You can mock the class, and any or all of its constructors, using JMockit.

It's a mocking toolkit for Java which lets you mock just about anything. Even if the class is non-public and/or nested, it can still be mocked. There are several mechanisms in JMockit that can be used for that. The toolkit distribution contains lots of sample JUnit tests as well.

If the class implements some interface or extends an abstract class, you can tell JMockit to "capture" and mock implementations of the base type on demand, as they are loaded by the JVM, and even assign the created instances to a field in the test class.

Rogério
  • 16,171
  • 2
  • 50
  • 63
0

If there are only private constructors, you can still use reflection in order to be able to access them from outside that class.

Nathaniel Flath
  • 15,477
  • 19
  • 69
  • 94
  • But this won't help you extend the class. The compiler won't let you extend a class with only private constructors. – Eddie Jun 17 '09 at 01:20