I am trying to write tests for a piece of code that uses the inner class of the following object as an input (I've generalized the names).
public class MockOuterClass implements OuterClass, Mock {
static class MockInnerClass implements InnerClass {
//fields and methods of the nested class
}
//methods of the outer class
}
Now since the inner class does not have a visibility tag, it defaults to "protected." Here lies my issue: since my tests and source code are in separate packages, how can I create an instance of this inner object? I attempted this:
MockOuterClass.MockInnerClass test = new MockOuterClass.MockInnerClass();
When I do this, Eclipse says that this line is unacceptable (which I assumed was the case, but it was wishful thinking) since MockInnerClass defaults to protected and thus cannot be used outside its package. Is there a way I can use this class somehow? I did not write the source code, so I am unsure if the lack of a "public" tag on the inner class was intentional or the programmer's mistake.
Thank you in advance.
A bit of an aside, not an actual answer, but I have always put my tests into the same package as the classes being tested. At least, as much as possible, there are a few very rare cases where this is impossible.
Why are you using a different package? Is there a good reason to do so?
Now, back to an answer, if you insist on testing from a separate package, unless MockOuterClass exposes some method to construct (or expose) the MockInnerClass, you are stuck. (I guess you could try using Reflection but that is getting desperate.) However, as several have commented, the author of the class "intended" for the inner class to be hidden, a. la. Kent Beck.
In other words, if you follow Kent Beck, you should be writing tests that target MockOuterClass, NOT MockInnerClass. The inner class is a "non public detail".
If this code wasn't written by you and declares a non-public static class (side-note: it defaults to package-protected, which is very different to protected), chances are the writer intends to hide the class from your use. In short, there is no way to access the class from outside the package, and you probably shouldn't be trying to.
Related
I have a Java class that is about 4,000 lines long (lots of methods). This class then uses about 200 small classes that only it needs, so another 4,000 lines of code.
If this was C# I would put those other in a partial class file so different file, but they would remain private nested classes only visible to the parent class.
Is there a way to do this in Java? I'm not asking for some methods to be in a distinct file, but for private nested classes to be in a distinct file.
thanks - dave
You can't make a class private to only another class while putting it in a different file.
Use no class access modifier
What you can do is put the classes in separate files with no access modifiers (omit "public"), which will make them package-private, i.e. visible only within its own package. See also the official Access Control tutorial.
UtilClasses.java:
package OurPackage;
class UtilClass1
{
}
class UtilClass2
{
}
MainClass.java:
package OurPackage;
public class MainClass
{
UtilClass1 iAmAUtilClass;
}
Use interfaces or inheritance
You can also achieve something similar with either interfaces or inheritance, by omitting the access modifier from the nested class. This would also be package-private, but this might be preferable to the above in some circumstances, since it avoids having all the nested classes at the top level.
BaseInterface.java:
package OurPackage;
interface BaseInterface
{
class UtilClass1
{
}
}
MainClass.java:
package OurPackage;
public class MainClass implements BaseInterface
{
UtilClass1 iAmAUtilClass;
}
You can also use a base class instead of an interface and extend that with roughly the same effect.
You don't need to implement BaseInterface gain access to its nested classes, but, if you don't, you'd need to use BaseClass.UtilClass1 instead of just UtilClass1.
Inner private classes can't be "extracted" and still be visible only to one particular class. One solution is already mentioned in the comments: Create a package that contains the "main" class and all the previously inner classes and make the inner classes package visible. This would also allow you to create unit tests testing for the correct functionalities of the inner classes, which is something that is most likely currently not happening simply because the inner classes can't be "reached" by a unit test at the moment.
Concepts like declaring "friendships" between classes like in C++ don't exist in Java.
You can replace the inner classes with top-level ones, but you'll have to rewrite a lot of things by hand that the compiler auto-wires for you with the inner-class relationship. To the Virtual Machine, an inner class is nothing special, it's just another class in the same package as the outer class with a fancy name. But the compiler creates a lot of helper constructs under the hood, that you have to reconstruct by hand (or have some refactoring tool do that for you):
The inner class can refer to the outer this instance, by prefixing it with the outer class name. You need to pass the outer this into your inner constructor and store it in a field like outerThis to get access.
In the source code, you can call the outer-class methods directly. You need to rewrite it like outerThis.method(). The same applies to fields.
For private outer methods and fields to become accessible, the compiler creates bridge constructs for you. You have to either change access modifiers or create package-private bridge methods yourself.
In the end, you'll have the former inner classes at least package-visible and being more verbose than the original ones, but on the other hand you'll get better isolation and testability.
In Swift, to test a default access level class, one can put #testable in the test class header, making the internal access level class accessible and testable from the test package, without everything in the class public. I was wondering if Java has a way to access the same purpose?
How can I test a default access level class in Java from the test package without making everything in the class public?
There are #VisibleForTesting annotations in some java libs, but generally it does not prevent illegal access. Even making package protected does not solve all the issues as still some other classes can use testing code, which can lead to some unexpected behaviour. I recently stumbled upon nice construct that allows you to show the intentions about exposing some methods for tests
public class A{
private int someMethodYouWantToTest(){}
private Testability testability = new Testability();
class Testability{
int exposedMethodForTest(){
someMethodYouWantToTest()
}
}
}
And then in your test class
public class Test{
private A underTest = new A()
public void testHiddenMethod(){
a.testability.exposedMethodForTest()
}
}
This way you private method is private, and only access if by dedicated testability inner class that clearly states its purpose, so no one by accident calls your method outside of tests. This solves issues with package protected businness methods that may be called from other places but were really meant to be private.
In Java, the only thing you can do is make things package protected if you want them to be used from your test code (that is: if you don't want them to be public).
Example: my classes very often look like
class Whatever
public Whatever() { this(new A(), new B()); };
Whatever(A a, B b) { ...
allowing me to use the second constructor for unit tests that require dependency injection; and at the same time relying on the "convention" that production code should prefer to always use the public constructor.
So even when I have classes that I don't want to be used outside of my package ... i make the constructor public to indicate: use this one please.
The idea is basically that your production code and test code resides in identically-named packages.
In other words: Java doesn't have this nice feature of giving access only to test code.
Quoting an answer to a similar question
"
You generally don't unit test private methods directly. Since they are
private, consider them an implementation detail. Nobody is ever going
to call one of them and expect it to work a particular way.
You should instead test your public interface. If the methods that
call your private methods are working as you expect, you then assume
by extension that your private methods are working correctly."
This is equivalent to option 1 in this link
If 1 does not fit your goals, you can try Approach 2,3 and 4 mentioned in the link
Sure it is not perfect that one has to make methods visible for testing that would otherwise be private, even if it is only in the classes own package.
On the other side, it is anyway recommended (and has many great benefits) not to depend on impelementations but on Interfaces.
That means: Give the client an Interface that declares only the methods you want to expose and make the methods you have to test in your implementation protected and do not include them in the interface.
Ok, let me start it with the following example to get a brief example
public class ClassA{
______ static final String MODULE = "[ClassA]";
}
in the blank space, I came across many code snippet it has some times public or protected or private but could not understand the which one is the best and why?.I know protected is best for subclass implementation but then subclass to has MODULE variable.
basically MODULE is used in logging activities like for example
System.out.println(MODULE+"given message");
in-short which is best way to use for accessing?
Like anything, you should give it the strictest access level that makes sense.
If it will only be used inside the class, use private. If it will only be used inside the package, use package access. If it could be used in subclasses, use protected. If it could be used by anyone, use public.
This applies to every class member in every programming language - it is by no means specific to fields named MODULE in Java.
Basically MODULE is used in logging activities...
Then I would suggest to make it private, because it will not be used outside the class (assuming that other classes have similar static constants).
I need check with junit that method of nested anonymous class invoked. But this class is private. Does there exist a way to test it without changing visiblity and logic of work? It may be that a common way exists to resolve similar problems?
The fact that the class is private or anonymous means that the implementation details are private. In general, your tests should not be depending upon implementation details, but should be testing behaviour, not the specific implementation.
The only way is to test the method that creates the object of the anonymous inner class, or to make it non-anonymous and non-private. (I've seen a fair amount of code that makes it default-visibility and uses a #VisibleForTesting annotation.)
You should not test that private class directly.
Most likely it's just a small class used as a util or it implements some broad, public interface.
In the first case just test class that wraps up the private class, and don't worry about private one at all. You can treat it as an implementation detail.
In second case just test that class against it public interface.
If I'm wrong about your code, then my advise would be to change design a bit, move wrapper class into separate package, extract private class to package level and test it directly.
Last way would be to mark it as #VisibleForTesting (annotation from Guava library) and raise visibility to package private (default).
I quite agree with Matthew Farwell when he says:
In general, your tests should not be depending upon implementation
details, but should be testing behaviour, not the specific
implementation.
However, tests call out for good design. If you really feel you should test that class directly, then that's a hint that that class should be a normal public class (and not an inner anonymous).
I have been facing so many problem using the anonymous class like I can't perform the instanceOf test neither can I implements multiple interface, so could someone please explain what I can or can not do with the anonymous class in java ?
The purpose of an anonymous inner class is to extend and instantiate an existing class or implement a single interface in one step.
Its limitations can be derived from the above:
Only one non-final class can be extended or one interface implemented.
Only final local variables of the enclosing method can be accessed. (This is due to the fact that normal local variables will be out of scope by the time any methods of the inner class will be invoked.)
You can't define a constructor. (The class has no name.)
If you need multiple interfaces, you can use a local inner class, which is like a normal inner class, with its own name, but defined within a method. I have to admit I've never seen it used in practice and I see very little reason for anyone to do so, hopefully someone will come up with an example.
Anonymous classes work whenever
you never need to refer to the class itself
you only need to extend a single class or implement a single interface
...but other than that there aren't really any significant constraints. This works fine in a lot of cases: for example, many cases when you're defining callbacks, listeners, or the like.