views:

842

answers:

7

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?

+10  A: 

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 only has private constructors then no, it can't.

Steve Reed
The class in question has only private constructors, including the no-argument one, so I guess I'm just out of luck.
Ben S
Looks like that class isnt very friendly in terms of testing. You really should be using interfaces rather than concerete types...
mP
So then you're testing a singleton? This always turns out to be a pain in the butt.
matt b
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
Yes, the object I'm trying to mock is a singleton who's only inheritance comes from Object and has no interfaces...
Ben S
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
+2  A: 

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).

Dmitriy Matveev
A: 

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
But this won't help you extend the class. The compiler won't let you extend a class with only private constructors.
Eddie
A: 

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

javamonkey79
+3  A: 

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
The class I was looking to mock was a Blackberry class which I have no control over.
Ben S
+2  A: 

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
A: 

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.

Rogerio