Change private member to default for testing - java

Is that good idea to change private class members to default(package access) for testing their behavior? I mean test case should destinate in test directory but in same package as tested member's class.
EDIT: All you guys tell the true. But classes have helper private methods often. And these methods can be complicated so need to be tested. And that is too bad - to test public methods for ensure correct working for private complicated methods. Don't you think so?

I generally prefer writing my classes and tests in a way that writing the tests against the public API makes sense. So basically I'm saying if you need to access the private state of your class under test you're probably already too involved in the internals of that class with your test..

No, it isn't. Because changing the test object may change the result. If you really need to call private members or methods during test, it's safer to add an accessor. This still changes the class, but with a lower risk. Example:
private void method() { /* ... */ }
// For testing purpose only, remove for production
#Deprecated // just another way to create awareness ;)
void testMethod() {
method();
}
OK - one more solution, if you need to test private methods: you can call any method with reflection and instantiation API.
Assuming, we have:
public class SomeClass {
private Object helper(String s, String t) { /* ... +/ }
}
then we can test it like
#Test public void testHelper() {
try {
SomeClass some = new SomeClass();
Method helperMethod = some.getClass().getDeclaredMethod("helper", String.class, String,class);
helperMethod.setAccessible(true);
Object result = helperMethod.invoke(some, "s", "t");
// do some assert...
catch(Exception e) {
// TODO - proper exception handling
}
}

I understand what you mean about needing to test private methods, and I also see why people say only test the public methods. I have just encountered some legacy code that has a lot of private methods, some of which are called by public methods, but some are threads, or called by threads, which are kicked off when the object is constructed. Since the code is riddled with bugs and lacks any comments I am forced to test the private code.
I have used this method to address the issue.
MainObject.cs
class MainObject
{
protected int MethodOne(); // Should have been private.
....
}
TestMainObject.cs
class ExposeMainObject : MainObject
{
public int MethodOne();
}
class TestMainObject
{
public void TestOne()
{
}
}
Since the test objects aren't shipped I can't see a problem with it, but if there is please tell me.

Testing trumps privacy modifiers. Really, how often is a bug caused by having "a little too much" visibility for a method? Compared to bugs caused by a method that was not fully tested?
It would be nice if Java had a "friend" option, like C++. But a limitation in the language should never be an excuse for not testing something.
Michael Feathers chimes in on this debate in "Working Effectively with Legacy Code" (excellent book), and suggests that this may be a smell of a sub-class that wants to be extracted (and have public methods).
In our shop (~ 1M LOC), we replace 'private' with '/TestScope/' as an indicator that a method should be effectively private, but still testable.
Trying to circumvent 'private' with reflection is IMHO a smell. It's making the tests harder to write, read, and debug in order to retain a 'fetish' of privacy, which you're working around anyway. Why bother?

Related

Why does only the class with the static method have the error: "Add a private constructor to hide the implicit public one."?

Using Java. The below is a single program that contains 2 methods that are called in another Class program that has the main (which proves that non-static methods require objects to be created first). HasAStaticMethod has an orange SonarLint error. Why doesn't the class NotStatic have an error, too?
public final class Test {
private Test () {
}
}
class HasAStaticMethod {
//private HasAStaticMethod(){}
public static void myPrint(String s) {
System.out.println(s);
}
}
class NotStatic {
public void myPrint(String s) {
System.out.println(s);
}
}```
Why does only the class with the static method have the error: “Add a private constructor to hide the implicit public one.”?
Creating an instance of HasStaticMethod would be a programmer mistake since it can serve (almost) no useful purpose ... as well as a harmful one (see below).
Declaring a private constructor will cause that programmer mistake (i.e. mistakenly instantiating HasStaticMethod) to be flagged as a compilation error.
This is a good thing.
Why doesn't the class NotStatic have an error, too?
Because you need an instance of NoStatic in order for call NoStatic.myPrint. So you need a non-private constructor to make the instance. A default constructor will do ... because that will be public.
NoStatic.myPrint(); // compilation error
new NoStatic().myPrint(); // OK
You don't need an instance in the HasStaticMethod case. The correct way to use it is:
HasStaticMethod.myPrint(); // OK
You could write this:
new HasStaticMethod().myPrint(); // compiles ... but bad
... but it doesn't do what the reader (most likely) thinks it does. The instantiation of the class is pointless, and calling a static method via an instance reference is downright misleading. That is the reasoning behind the IDE hint: to stop the programmer (who is using your HasStaticMethod class) from accidentally or deliberately writing that kind of nonsense.
I think you may be thinking about this from the wrong perspective1. The goal is to write Java code that 1) works and 2) can be read and maintained by someone else. To that end, it is good thing when the IDE / Sonar warns us we are doing something that is liable to lead to problems. (And indeed, this is why we use tools like Sonar.)
Now you are free to twiddle with the Sonar settings to turn off this warning if you don't like it. Or stop using Sonar altogether. (But check with your coworkers and manager first, because they might have some opinions on that course of action.)
But my advice is to just add the private constructor and declare the utility class as final ... as Sonar suggests. It is (IMO) a good thing to do.
1 - This should not be about "freedom of expression" or "personal choice". This is not poetry ...

using instance initializer to deal with constructor overloading

A pattern I sometimes see is that a constructor might take either no argument or one argument. Now, I wonder whether the 'better' approach is to move common code to the most defined constructor - or to use the instance initializer in this case. For example, one way of always generating an ID for every class created:
public SomeClass(){
this("Hello");
}
public SomeClass(String s){
this.s = s;
this.id = generateId();
}
versus writing it like this:
{
this.id = generateId(); // method does not depend on the class
}
public SomeClass(){
this("Hello");
}
public SomeClass(String s){
this.s = s;
}
The reason for using the Instance Initializer would be because I want to always run the method when the class is created, and in the future someone else might change the class's constructors and forget to do this. Whilst it is less likely to remove the instance initializer (without realizing what you are doing).
But on the other hand, I am not sure how about readability in this case.
The examples are a bit contrived, not real-world examples.
The reason for using the Instance Initializer would be because I want
to always run the method when the class is created, and in the future
someone else might change the class's constructors and forget to do
this. Whilst it is less likely to remove the intance initializer
(without realising what you are doing).
Doing the one (using the Instance Initializer) or the other one (constructor) should not be used as trick to avoid coding error when the class is modified.
And anyway, why Initializer would give better insurance about it ?
You want to ensure that the constructor do what it designed to do ?
Writing an unit test that validates this behavior and that is automatically executed at each build.
That's all.
I think the reasonable solution here:
private final Whatever id = generateId();
In other words:
make sure the compiler knows that this should be initialized (so use final)
and instead of using an init block (rather uncommon) simply do initialize once, "in place"
I have never seen a use of instnace initializer in real life. (I actually did see it and played with it for a bit in one of theoretical questions on this site). In real life though you often can see a static initializer block:
public class Bla {
static {
//do something
}
....
}
As for common code what could be done is to have a method called init() that is called by all constructors. In your example it would look like
public SomeClass(){
this("Hello");
}
public SomeClass(String s){
init();
this.s = s;
}
private init() {
this.id = generateId(); // method does not depend on the class
}

How to check for the existance of a method? [duplicate]

There is a possible optimization I could apply to one of my methods, if I can determine that another method in the same class is not overridden. It is only a slight optimization, so reflection is out of the question. Should I just make a protected method that returns whether or not the method in question is overridden, such that a subclass can make it return true?
I wouldn't do this. It violates encapsulation and changes the contract of what your class is supposed to do without implementers knowing about it.
If you must do it, though, the best way is to invoke
class.getMethod("myMethod").getDeclaringClass();
If the class that's returned is your own, then it's not overridden; if it's something else, that subclass has overridden it. Yes, this is reflection, but it's still pretty cheap.
I do like your protected-method approach, though. That would look something like this:
public class ExpensiveStrategy {
public void expensiveMethod() {
// ...
if (employOptimization()) {
// take a shortcut
}
}
protected boolean employOptimization() {
return false;
}
}
public class TargetedStrategy extends ExpensiveStrategy {
#Override
protected boolean employOptimization() {
return true; // Now we can shortcut ExpensiveStrategy.
}
}
Well, my optimization is a small yield on a case-by-case basis, and it only speeds things a lot because it is called hundreds of times per second.
You might want to see just what the Java optimizer can do. Your hand-coded optimization might not be necessary.
If you decide that hand-coded optimization is necessary, the protected method approach you described is not a good idea because it exposes the details of your implementation.
How many times do you expect the function to be called during the lifetime of the program? Reflection for a specific single method should not be too bad. If it is not worth that much time over the lifetime of the program my recommendation is to keep it simple, and don't include the small optimization.
Jacob
Annotate subclasses that overrides the particular method. #OverridesMethodX.
Perform the necessary reflective work on class load (i.e., in a static block) so that you publish the information via a final boolean flag. Then, query the flag where and when you need it.
maybe there is a cleaner way to do this via the Strategy Pattern, though I do not know how the rest of your application and data are modeled but it seem like it might fit.
It did to me anyhow when I was faced with a similar problem. You could have a heuristic that decides which strategy to use depending on the data that is to be processed.
Again, I do not have enough information on your specific usage to see if this is overkill or not. However I would refrain from changing the class signature for such specific optimization. Usually when I feel the urge to go against the current I take it as a sing that I had not forseen a corner case when I designed the thing and that I should refactor it to a cleaner more comprehensive solution.
however beware, such refactoring when done solely on optimization grounds almost inevitably lead to disaster. If this is the case I would take the reflecive approach suggested above. It does not alter the inheritance contract, and when done properly needs be done once only per subclass that requires it for the runtime life of the application.
I know this is a slightly old question, but for the sake of other googlers:
I came up with a different solution using interfaces.
class FastSub extends Super {}
class SlowSub extends Super implements Super.LetMeHandleThis {
void doSomethingSlow() {
//not optimized
}
}
class Super {
static interface LetMeHandleThis {
void doSomethingSlow();
}
void doSomething() {
if (this instanceof LetMeHandleThis)
((LetMeHandleThis) this).doSomethingSlow();
else
doSomethingFast();
}
private final void doSomethingFast() {
//optimized
}
}
or the other way around:
class FastSub extends Super implements Super.OptimizeMe {}
class SlowSub extends Super {
void doSomethingSlow() {
//not optimized
}
}
class Super {
static interface OptimizeMe {}
void doSomething() {
if (this instanceof OptimizeMe)
doSomethingFast();
else
doSomethingSlow();
}
private final void doSomethingFast() {
//optimized
}
void doSomethingSlow(){}
}
private static boolean isMethodImplemented(Object obj, String name)
{
try
{
Class<? extends Object> clazz = obj.getClass();
return clazz.getMethod(name).getDeclaringClass().equals(clazz);
}
catch (SecurityException e)
{
log.error("{}", e);
}
catch (NoSuchMethodException e)
{
log.error("{}", e);
}
return false;
}
Reflection can be used to determine if a method is overridden. The code is a little bit tricky. For instance, you need to be aware that you have a runtime class that is a subclass of the class that overrides the method.
You are going to see the same runtime classes over and over again. So you can save the results of the check in a WeakHashMap keyed on the Class.
See my code in java.awt.Component dealing with coalesceEvents for an example.
it might be another workaround which is similar to override another protected method returns true/false
I would suggest creating an empty interface, markup interface, then make the subclass implements this interface and inside the superclass check that this instance is instanceof this interface before calling the overridden expensive method.

Is it a good approach to override methods in a class which you don't want to test?

Suppose my class has 3 methods:
public void parent() throws Exception {}
public String child_1(String arg_1) throws IOException {}
public boolean child_2(String arg_1, String arg_2) throws SQLException {}
parent() calls child_1() and child_2(), like:
public void parent() throws Exception {
// Do some complicated stuff
child_1("str1");
// More stuff
child_2("str1", "str2");
// More stuff
}
Now, if I have already tested child_1() and child_2() and I want to test only parent(), is it ok to override child_1() and child_2() and test only parent()? Something like this:
MyClass myClass = new MyClass() {
#Override
public String child_1(String arg_1) throws IOException {
return "expected_string_to continue_execution";
}
#Override
public boolean child_2(String arg_1, String arg_2) throws SQLException {
return true; // return expected boolean result to continueexecution;
}
};
myClass.parent();
By doing this, I can easily test my parent() and since child_1() and child_2() are already tested in other unit tests for this class, it does not do any cheating (atleast that's what I think, please correct me if I am wrong). Also, in real world, if chaild_1() and child_2() are doing something complicated, this approach makes testing easy, we do not redundantly check time consuming code.
My question is, whether it is a right approach? If not, what is the downside and most importantly, what is the right approach? If someone can explain with the same above example, that will be awesome.
Thanks a lot.
I would say overriding methods is something you should avoid in general since it most likely violates the Liskov substitution principle. Test code is no special: it should follow the same strict principles as production code. The only exception I can think of is if you are testing legacy code with high coupling between components and overriding is the only option. But when writing new code I don't see any reason.
I think #samlewis is on to something: if you feel you want to test parent() in isolation for some reason, then child_1() and child_2() should probably be in own classes that are injected into parent(). Avoid testing anything smaller than a class. If you need to test something smaller you probably have a responsibility that wants to be extracted (Single responsibility principle).
A hint that child_1() and child_2() actually belongs in other classes is that they are public and that the public method parent() calls it. Public methods should typically only call non-public methods (although there are probably exceptions).
Or did you make the child methods public so that you can test them? If so, have a look at this answer.
Are child_1() and child_2() really consumed from the outside, or did you make them public so you could test them ?
As Torbjörn points out, it's rare to see a public method calling 2 other public methods on the same instance. Submethods typically contain behavior that is internal to a class and shouldn't be exposed to the world. Their names often reflect another level of language than the public facing contracts of the class - they are expressed in the object's own private jargon.
Assuming you can make child_1() and child_2() private, you don't have to test them explicitly, they will be tested indirectly by the parent() test.

How to prevent public methods from being called from specific classes

I have an existing class into which I want to add a method. But I want the method to be called only from a specific method from a specific class. Is there any way that I can prevent that call from other classes/methods?
For example, I have an existing class A
public final class A
{
//other stuff available for all classes/methods
//I want to add a method that does its job only if called from a specific method of a class, for example:
public void method()
{
//proceed if called from Class B.anotherMethod() else throw Exception
}
}
One way of doing this is getting the StackTrace inside the method() and then confirming the parent method?
What I am looking for is a solution that is more clean and advisable solution like a pattern or something.
To be honest, you have painted yourself into a corner here.
If classes A and B are not related and not members of the same package, then visibility won't solve the problem. (And even if it did, reflection can be used to subvert the visibility rules.)
Static code analysis won't solve the problem if the code can use reflection to call the method.
Passing and checking B.this as an extra parameter to A.method(...) doesn't help because some other class C could pass a B instance.
This leaves only the stacktrace approach1... or giving up and relying on the good sense of the programmer2 not to call methods that they shouldn't.
The ideal solution is to revisit the design and/or coding decisions that got you into this mess.
1 - See other answers for examples that use annotations, a security manager, etc to conceal the stacktrace stuff from the application programmer. But note that under the hood you are adding probably hundreds, possibly thousands of instructions overhead per method call.
2 - Do not underestimate the programmer's good sense. Most programmers, when they see advice not to call some method, are likely to follow that advice.
The right way to do this would be a SecurityManager.
Define a permission which all code which wants to call A.method() has to have, and then make sure only B and A have that permission (this also means that no class has AllPermission).
In A, you check this with System.getSecurityManager().checkPermission(new BMethodPermission()), and in B you call the method inside of AccessController.doPrivileged(...).
Of course, this requires that a security manager is installed (and it uses suitable policies) - if it isn't, all code is trusted and everyone can call everything (if necessary, with Reflection).
You might consider using an interface. If you're passing in the calling class, you can confirm that the class is of the appropriate type.
Alternatively, if you're using Java, you can use "default" or "package" level access (e.g. void method() vs. public void method()). This will allow your method to be called by any class inside the package and does not require that you pass the class to the method.
The only way to check for sure at run time is to take a stack trace. Even if its private you can access the method via reflections.
A simpler way to do this would be to check usages in your IDE. (provided its not called via reflections)
As others have mentioned, using the stack trace is one way to implement the functionality that you are looking for. Generally, if one needs to "block" callers from a public method, it could be a sign of poor design. As a rule of thumb, use access modifiers that restrict the scope as much as possible. However, making a method package-private or protected is not always an option. Sometimes, one may want to group some classes in a separate package. In that case, the default (package-private) access is too restrictive, and it usually does not make sense to subclass, so protected is not helpful either.
If restricting calling to certain classes is desired, you can create a method like:
public static void checkPermission(Class... expectedCallerClasses) {
StackTraceElement callerTrace = Thread.currentThread().getStackTrace()[3];
for (Class expectedClass : expectedCallerClasses) {
if (callerTrace.getClassName().equals(expectedClass.getName())) {
return;
}
}
throw new RuntimeException("Bad caller.");
}
Using it is very simple: just specify what class(es) can call the method. For example,
public void stop() {
checkPermission(ShutdownHandler.class);
running = false;
}
So, if the stop method gets called by a class other than ShutdownHandler, checkPermission will throw an IllegalStateException.
You may wonder why checkPermission is hard-coded to use the fourth element of the stack trace. This is because Thread#getStackTrace() makes the most recently called method the first element. So,
getStackTrace()[0] would be the call to getStackTrace itself.
getStackTrace()[1] would be the call to checkPermission.
getStackTrace()[2] would be the call to stop.
getStackTrace()[3] would be the method that called stop. This is what we are interested in.
You mentioned that you want methods to be called from a specific class and method, but checkPermission only checks for class names. Adding the functionality to check for method names requires only a few modifications, so I'm going to leave that as an exercise.
Make proper use of protected
The standard way to do this in java is to put Class B and Class A in the same package (maybe a subpackage of your current application) and use the default visibility.
The default java visibility is "package-private" which means everything in that package can see your method, but nothing outside that package can access it.
See Also:
Is there a way to simulate the C++ 'friend' concept in Java?
Assuming that you only need to apply this restriction to classes within your project, static analysis could work for you - for example an ArchUnit test:
package net.openid.conformance.archunit;
import com.google.gson.JsonElement;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.AccessTarget;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import net.openid.conformance.testmodule.OIDFJSON;
import org.junit.Test;
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.*;
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.are;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
public class PreventGetAs {
#Test
public void doNotCallJsonElementGetAs() {
JavaClasses importedClasses = new ClassFileImporter().importPackages("net.openid.conformance");
JavaClasses allExceptOIDFJSON = importedClasses.that(DescribedPredicate.not(nameContaining("OIDFJSON")));
ArchRule rule = noClasses().should().callMethodWhere(
target(nameMatching("getAs[^J].*")) // ignores getAsJsonObject/getAsJsonPrimitive/etc which are fine
.and(target(owner(assignableTo(JsonElement.class)))
)).because("the getAs methods perform implicit conversions that might not be desirable - use OIDFJSON wrapper instead");
rule.check(allExceptOIDFJSON);
}
}
You can do it by using annotations and reflection. I will report a similar case, i.e. the case where you can let the method being called only by specific methods from extenal classes. Suppose that the class that must be "protected" by a whatsoever invocation of the its public methods is Invoked, while Invoker is the class tha has a method enabled to invoke one or more methods from Invoked. Then, you can do something like reported in the following.
public class Invoked{
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public static #interface CanInvoke{}
public void methodToBeInvoked() {
boolean canExecute=false;
try {
//get the caller class
StackTraceElement element = (new Throwable()).getStackTrace()[1];
String className = element.getClassName();
Class<?> callerClass = Class.forName(className);
//check if caller method is annotated
for (Method m : callerClass.getDeclaredMethods()) {
if (m.getName().equals(methodName)) {
if(Objects.nonNull(m.getAnnotation(EnabledToMakeOperationRemoved.class))){
canExecute = true;
break;
}
}
}
} catch (SecurityException | ClassNotFoundException ex e) {
//In my case does nothing
}
if(canExecute){
//do something
}
else{
//throw exception
}
}
}
and the Invoker class is
public class Invoker{
private Invoked i;
#Invoked.CanInvoke
public void methodInvoker(){
i.methodToBeInvoked();
}
}
Note that the method that is enabled to invoke is annotated with the CanInvoke annotation.
The case that you requested is similar. You annotate the classes/method that cannot call the public method and then you set to true the canExecute variable only if the method/class is not annotated.
You can use a tool like Macker and add it to your build process to check some rules are respected, like
<?xml version="1.0"?>
<macker>
<ruleset name="Simple example">
<access-rule>
<deny>
<from class="**Print*" />
<to class="java.**" />
</deny>
</access-rule>
</ruleset>
</macker>
It will NOT prevent you from writing wrong code but if you use Maven or another build system it can raise an error during your build process.
This tools work at a "class" level not at a "method" level but I do not see the point of preventing the call of only one method from a certain class ...
I realise your use case states 'specific method in specific class', but I don't think you can reliably solve this at design time (and I can't think of a use case where this would have to be enforced anyway).
The following example creates an easy design time solution for restricting the access of a class' method to a particular class. It can, however, be easily extended to multiple allowed classes.
It is achieved by defining a public inner class with a private constructor that acts as a key to the method at hand. In the following example the class Bar has a method that should only be called from an instance of the Foo class.
Class Foo:
public class Foo
{
public Foo()
{
Bar bar = new Bar();
bar.method(new FooPrivateKey());
}
public class FooPrivateKey
{
private FooPrivateKey()
{ }
}
}
Class Bar:
public class Bar
{
public Bar()
{
}
public void method(FooPrivateKey fooPrivateKey)
{
if(fooPrivateKey == null)
{ throw new IllegalArgumentException("This method should only be called from the Foo class.");}
//Do originally intended work.
}
}
I don't think this is by any means safe for things like reflection or even things like FooPrivateKey.class.newInstance(), but this will at least warn the programmer a little more obtrusively than a simple comment or documentation, while you don't have to look in to more complicated things like what was suggested by people like Roberto Trunfio and Ronan Quillevere (which are perfectly viable answers as well, just too complicated for most situations in my opinion).
I hope this is sufficient for your use case.

Categories