I am writing a Junit for a method with multiple parameters and having private access specifier. I am using Java reflection to achieve this. However, one of the parameter for this private method is private class. I am doing below:
ClassHavingPrivateMethod object = new ClassHavingPrivateMethod();
object.getClass().getDeclaredMethod(PRIVATE_METHOD_NAME, Param1.class, <This parameter is a private class Inside ClassHavingPrivateMethod>)
How can I proceed?
EDIT
I agree on the point that I should not write a test case for a private method with reflection and it should always be accessed through a wrapper public method. However, is there any way to achieve the above objective through reflection. Even though, I am not going to write my test case through reflection but I am eager to know about it.
Any help is really appreciated.
One of the way you can try by changing the access from private to default. By changing the access level to default the method can be accessed only from the same package (still restricted access) on the other hand since your test class and class under test will be under same package , the test class can call that method directly, without doing any trick.
Example :
package com.test;
class SomeClass {
String defaultMethod(){
...
}
}
package com.test;
class SomeClassTest {
public void testDefaultMethod(){
SomeClass testObject = new SomeClass();
testObject.defaultMethod();
}
}
Hope it will help.
Related
class Example extends Parent{
public Example() {
super(Example.class)
}
whenever I am trying the
public class Test{
#InjectMock Example example
#BeforeMethod
#BeforeTest
public void setUp(){
MockitoAnnotations.initMocks(this)
}
}
It is giving the above error mentioned.
Any help is appreciated.
there are a pair of things in your code which not used correctly. I think there is a bit of confusion and is not clear enough what you what to do. I'll try to explain e give you something to read.
#Injectmocks annotation in Test class
The #Injectmocks annotation is used to create a real instance of a class in which you want to inject #Mock objects.
Take a look here for some examples:
https://howtodoinjava.com/mockito/mockito-mock-injectmocks/ ,
https://www.baeldung.com/mockito-annotations
The annotation is an instance field annotation. This means that you cannot use that as you are doing on a method declaration, but you need to use that instead on a field into the test class.
Let's suppose you want to test a method in a class, then you will use this annotation to create an instance of that class which contains the method to be tested. Roughly speaking with analogies, injectmock is like the Spring #Autowire annotation, although not the same.
I've noticed now that probably this is what you where trying to do (the puplished code of the test class has not been highlighetd correctly). You should put new line after #InjectMock Example example. In any case, I think there is a mistake in how you use the super keyword.
Call to super constructor in Example constructor.
I don't know what is the constructor in Parent class and how is done, but the rule is you pass arguments of the Parent construtor in super keyword. So for exampe, if this is your parent constructor:
public Parent(String name){
this.name = name}
then you need to do this in Example:
public Example(String name, String code) {
this.code = code;
super(name);
}
You are passing a .class in super(), not a field.
I would like to give you more help. I suggest you to post your code more clearly and with complete classes.
Nowadays we are on writing some core application that is all other application will be relying on. Without further due let me explain the logic with some codes,
We used to have a single java file that was 1000+ lines long and each application was having it as class inside, so when there was a change, each application had to edit the java file inside of it or simply fix one and copy to all. This is hard to implement as much as it is hard to maintain. Then we end-up with creating this as a separate application that is divided to smaller part, which is easy to maintain and also a core maybe a dependency to other application so we fix in one place and all other code applications are fixed too.
I've been thinking for a some great structure for this for a while want to use a builder patter for this as below
TheCore theCore = new TheCore().Builder()
.setSomething("params")
.setSomethingElse(true)
.build();
The problem arises now. Like so, I initialized the object but now I'm having access to that objects public class only. This application actually will have many small classes that has public functions that I don't want them to be static methods that can be called everytime. Instead I want those methods to be called only if TheCore class is initilized like;
// doSomething() will be from another class
theCore.doSomething()
There are some ideas I produced like
someOtherClass.doSomething(theCore)
which is injecting the main object as a parameter but still someOtherClass needs to be initialized or even a static method which doesn't make me feel comfortable and right way to that.
Actually I do not care if initializing TheCore would bring me a super object that includes all other classes inside initialized and ready to be accessed after I initialized TheCore. All I want in this structure to have a maintainable separate app and methods avaiable if only the main object which is TheCore is this circumstances is initialized.
What is to right way to achive it? I see that Java does not allow extending multiple classes even it if does, I'm not sure it that is right way...
Thanks.
After spending significant amount of time of thought I ended up that
// doSomething() will be from another class
theCore.doSomething()
is not suitable since many java classes could possibly have identical method names. So...
// doSomething() will be from another class
theCore.someOtherClass.doSomething()
would be a better approach.
To make it easier to understand I'll have to follow a complex path to explain it which is starting from the package classes first.
Think that I have a package named Tools and a class inside SomeFancyTool
main
└─java
└─com
└─<domainName>
├─Tools
| └─SomeFancyTool.java
└─TheCore.java
Now this SomeFancyTool.java must have a default access level which is actually package level access, because I don't want this classes to be accessed directly;
SomeFancyTool.java
package com.<domainName>.Tools
class SomeFancyTool{
public String someStringMethod(){
return "Some string!";
}
public int someIntMethod(){
return 123;
}
public boolean someBooleanMethod(){
return true;
}
}
So now we have the SomeFancyTool.java class but TheCore.java cannot access it since it is accesible through its Tools package only. At this point I think of an Initializer class that is gonna be in the same package, initialize these private classes and return them with a function when called. So initiliazer class would look like this;
ToolsInitializer.java
package com.<domainName>.Tools
public class ToolsInitializer{
private SomeFancyTool someFancyTool = new SomeFancyTool();
public SomeFancyTool getSomeFancyTool(){
return someFancyTool;
}
}
Since ToolsInitializer.java can initialize all functional private classes inside in Tools package and also can return them as objects to outside of the package scope, still we are not able to use these methods as we cannot import com.<domainName>.SomeFancyTool from TheCore.java because it is package wide accessible. I think here we can benefit from implementation of the java interface. A class that is not functional alone, so no problem even if it is accessed since it's methods will be nothing but declarations.
At this point I'll rename SomeFancyTool.java to SomeFancyToolImplementation.java which it will be implementing the interface and call SomeFancyTool.java to the interface itself.
SomeFancyTool.java (now as an interface)
package com.<domainName>.Tools
public interface SomeFancyTool{
public String someStringMethod();
public int someIntMethod();
public boolean someBooleanMethod();
}
and lets rename prior SomeFancyTool.java and implement the interface
SomeFancyToolImplementation.java (renamed)
package com.<domainName>.Tools
class SomeFancyToolImplementation implements SomeFancyTool{
#override
public String someStringMethod(){
return "Some string!";
}
#override
public int someIntMethod(){
return 123;
}
#override
public boolean someBooleanMethod(){
return true;
}
}
Now our structure has become like this with the final edits;
main
└─java
└─com
└─<domainName>
├─Tools
| ├─SomeFancyTool.java
| ├─SomeFancyToolImplementation.java
| └─ToolsInitializer.java
└─TheCore.java
Finally we can use our TheCore.java class to call all initializer classes with their methods to receive all these private classes inside as an object. This will allow external apps to call and initialize TheCore first to be able to access other methods.
TheCore.java
public class TheCore{
private SomeFancyToolImplementation someFancyTool;
public static class Builder{
private SomeFancyToolImplementation someFancyTool;
public Builder(){
ToolsInitializer toolsInitializer = new ToolsInitializer();
someFancyTool = toolsInitializer.getSomeFancyTool();
}
public Builder setSomeValues(){
//some values that is needed.
return this;
}
public Builder setSomeMoreValues(){
//some values that is needed.
return this;
}
public TheCore build(){
TheCore theCore = new TheCore();
theCore.someFancyTool = someFancyTool;
return theCore;
}
}
}
All Done and it is ready to use. Now the functional package classes and its methods that it relying on if TheCore is initialized or not, cannot be accessed with out TheCore. And simple usage of this Library from a 3rd Party app would simply be;
3rd Party App
TheCore theCore = new TheCore.Builder()
.setSomeValues("Some Values")
.setMoreSomeValues("Some More Values")
.build();
theCore.someFancyTool.someStringMethod();
Note: Note that a the ToolsInitializer.java is still accessible and could be used the get private method without first calling TheCore but we can always set a checker inside getSomeFancyTool() method to throw error if some prerequisites are not satisfied.
I do not still know if this is a functional structural pattern to use or its just some hard thoughts of mine. And don't know if some pattern is already exist that I just could not see yet but this is the solution I end up with.
I have a script with a global variable in my Groovy script
I have a problem using it inside a function. May I know the reason or the right way?
I'm gonna be using it for a logger. Other primitive data types can be accessed but this, I can't.
#Field def log = Logger.getLogger("NameOfLogger")
log.info("TEST")
testFunction()
private void testFunction() {
//cannot use the log variable here
}
I know now the cause. It's because I was declaring it as def
But I still don't know the real reason why def can't be used.
The following code works for me (I haven't tried with log but used online groovy console):
import groovy.transform.Field
import groovy.transform.Canonical
#Canonical
class Person {
String name
int age
}
#Field person = new Person("John", 30)
println "Global $person"
testFunction()
private void testFunction() {
println "Inside method: $person"
}
Output:
Global Person(John, 30)
Inside method: Person(John, 30)
So make sure you have proper imports first of all
Now, it worth mentioning that groovy creates an implicit class and Field annotation alters the scope of the global variable and moves it to be a field of that implicit class so that both person and testFunction will both belong to this class and there won't be a problem to access the field from within the method.
My intent is to do unit test of private methods and I understand on how to import the #VisibleForTesting and use it for a private method. I have done a quite a bit of search but unable to see a complete example that demonstrates this feature.
For eg:
class MyClass {
#VisibleForTesting
private double[] getWorkArray(double[] values,int length) {
:
:
return <some double array>
}
}
Now in JUnit, I must be able to do
#Test
public void testProvateMethod() {
MyClass object = new MyClass();
assertNotNull(object.getWorkArray(...);
}
But the difficult part is I am unable to comprehend/do the following
a) Snippet of maven compiler plugin for including the relevant annotation processor
b) Actually be able to test a private method. (since it throws error related to visibility of method)
I am unable to do it in action while I write a test in JUnit (due to the private access error). For eg: mvn clean test
Please provide a complete example to really all steps involved in getting the JUnit test of private methods done.
Firstly, I do not recommend to test private methods, unit tests should test public methods in most cases. If you have to test private methods, it usually indicates a bad design.
Regarding to #VisibleForTesting , it is used in package-methods in Guava, and not part of JUnit API. The annotation is just a tag to indicate the method can be tested, it even doesn't be loaded in JVM. So if you need to test non-public methods, make the methods package scope which is visible to unit test classes in same package.
Last, by using reflect can access private methods, if you really have to test them.
Testing a private method must be one of the bad patterns.
However, there are times when you often feel the urge to test private methods.
In this case, I personally use ReflectionTestUtils to test the method. This is because we wanted to keep the original intent of the private method, and only test the method. Below is an example of my sample.
MyClass myClass = new MyClass();
ReflectionTestUtils.invokeMethod(myClass, "getWorkArray", values, length);
One drawback is the fact that I get the name of the method as a String and it is quite a bit sad except for the fact that refactoring does not convert correctly in IDEA.
I hope it helps.
Thanks.
You can remove private keyword:
class MyClass{
#VisibleForTesting double[] getWorkArray(double[] values,int length) {
:
:
return <some double array>
}
}
Then you are able to:
MyClass object = new MyClass();
assertNotNull(object.getWorkArray(...);
in your test.
I guess this is a bad pattern, whats the best approach to fix it?
I mean I would like everybody using a constructor with 2 arguments,but I need to leave default constructor because its implementing a listener which classloads it without args. I would like to hide default constructor to anyone else but the listener handler which uses it, and make the other the unique point to instantiate.
Is there any kind of annotation? any privacy modifier for certain classes (system caller one is not in the same package)?
This seems fine to me. You would do the same thing if you want to instantiate a class differently during unit testing.
Oh, I see you need a constructor that has more access than protected but less than public. Unfortunately that's not possible.
You could put both your class MyClass and the listener MyListener that needs to use the empty constructor in the same package. Then, set the access of the empty constructor to package-level:
package com.stackoverflow.foo;
public class MyClass {
MyClass () { // package-private (no explicit access modifier)
}
public MyClass(int a, int b) { // public
}
}
package com.stackoverflow.foo;
public class MyListener {
private MyClass ref = new MyClass(); // MyListener is on the same package as MyClass, so this is valid
}
This way, you ensure that only classes that are on the same package as MyClass can use the default constructor.