I have a class file, and I just want to get the list of methods name in that class and print it o/p console.
Just assume that I have following methods in Test1 class
public class Test1{
public static void test1()
{
//some code
}
public static void test2()
{
//some code
}
public static void test3()
{
//some code here.
}
}
I just need to call all the above methods from another class in the specific order.
Like test1() first, and second test2() and followed by test3();
What I did like I just created
Method[] methodarray=Test1.getMethods();
if(methodarray.getName().startWith("test"))
{
sysout(methodarray.getName())
}
The above code print the method in specific order first time but not always. some times it prints 3rd method first and 1method seconds, and finally 2 method.
Can anybody tell me the reason?, and how to resolve this?.
-Sasi
Quote from the JavaDoc: "The elements in the returned array are not sorted and are not in any particular order.".
First of all, it's always best to avoid reflection where possible in a project. Most of the time it's used for testing purposes, or if there really is no other way. That being said, if your methods are indeed called test1, test2 and test3 and you want to execute them in this order, you can use the following steps:
Get all methods from the class (you've done that correctly with Method[] allMethods = Test1.getMethods();)
Loop through them and save all which start with "test" in a seperate list
Order that list with a Custom Sorting to sort the Methods of the seperate list by Method-Name. (See here for an example.)
Invoke & Execute them
Still, it takes three loops (or some Java 8+ LINQ-queries) and it doesn't make the code very clear to anyone, including yourself. It's better to just execute them one by one manually, i.e.:
public void someMethod(){
Test1.test1();
Test1.test2();
Test1.test3();
}
That's just my 2c. From the question it wasn't clear what the purpose of the methods are, or if there are more than three. I would suggest keeping away from reflection unless you really have no other way.
As you can read in the javadoc for getDeclaredMethods(), the returned Method[] doesn't follow a particular order.
You can sort the methods easily by using a LinkedHashMap, or any other Map implementation, that maintains order of elements. For example:
public class MethodTest {
private LinkedHashMap<String, Method> expectedMethodsInOrder;
void testOne(){
}
void testEight(){
}
void beforeEight(){
}
#Before
public void prepareMap(){
expectedMethodsInOrder = new LinkedHashMap<>();
expectedMethodsInOrder.put("testOne", null);
expectedMethodsInOrder.put("beforeEight", null);
expectedMethodsInOrder.put("testEight", null);
}
#Test
public void test(){
Method[] methods = MethodTest.class.getDeclaredMethods();
for(Method m : methods){
String name = m.getName();
if(expectedMethodsInOrder.containsKey(name)){
expectedMethodsInOrder.put(name, m);
}
}
System.out.println(expectedMethodsInOrder.values().toString());
}
}
Output:
[void Main.testOne(), void Main.beforeEight(), void Main.testEight()]
It's working as expected in Windows 7 but not in Windows 8. I have same setup on both environments, like JAVA JDK7, and Eclipse IDE JEE build. But reflection returns the method as Its mentioned in respective class file. But not in Windows 8. It seems to be environment issues.
I just wanna update my things which I observed. Please correct me If there is any other root cause.
-Sasi
Related
I have a few Management classes that are used for search methods, add, change and delete methods, print in table format method and write map to file method. The classes also have a container each as an attribute. Lets say there is a class X. This would be the class XManagement, and its container has objects of class X.
search() method returns the object of X, but first it gathers its ID via input.
add() method gathers input data for the creation of an object X, and the very last line of its code is for adding that object to its container.
change() method first searches for the object the user wants to change (via search() method), and then gathers data and changes the object via setter methods. It then calls the write() method for re-writing the file.
delete() method searches for the object (via search()), and then just removes it from its container, after which it calls the write() method.
The write() method is also void. It goes through the container for each object, and its data is then appended to a parse-able String, which is written to file.
Here are the examples:
public class XManagement {
protected Hashtable<Integer, X> xes = new Hashtable<>();
public XManagement(String fileName) {
// Constructor.
// Loads the input file, then parses it.
// Once parsed, the objects of X class are created.
// They are then put into the container (xes).
}
protected X search() {
// Both generic methods.
Integer uuid = enterInteger("ID");
return (X) find(uuid, xes);
}
public void add() {
Integer uuid = UUID(xes); // Generic method, generates UUID.hashCode()
// and checks for duplicates.
String a = enterString("Name");
Date d = enterDate("Start");
// ...............
X x = new X(uuid, a, d, etc);
xes.put(x.getID(), x);
write();
}
public void delete() {
X x = search();
xes.remove(x.getID(), x);
write();
}
public void change() {
X x = search();
String a = enterString("Name");
x.setA(a);
Date d = enterDate("Start");
x.setD(d);
// .......................
write();
}
protected void write() {
File file = new File("x.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(file));
String curr = "";
for (int id : xes.keySet()) {
curr += xes.get(id).getA() + "|" + xes.get(id).getD() + "|"; // etc
}
out.write(curr);
// There's, naturally, try/catch/finally here. For the sake of simplicity, I left it out here.
}
}
Class X goes like this:
public class X {
String a;
Date d;
// etc
public X(String a, Date d) {
this.a = a;
this.d = d;
}
// Getters and setters.
}
It's a lot more complicated than that, I just tried to keep it simple here to get some help - I'll try to figure out the harder stuff when I get the basics.
In some management classes, methods and constructors have the instances of other Management classes as their input parameters, so that they can call their methods inside, because most of them are connected. Let's say the Y class has X as an attribute, and when I create a Y object in YManagement add() method, I need to be able to choose one from all the available X objects from xes, via the search() method contained in XManagement.
I decided to keep it simple for now, but if you want, you can tell me how to approach testing where I'd have instances of other Management classes as an input.
How do I write detailed JUnit 5 test cases for these methods?
Sorry if I made a mistake somewhere in the code, I haven't copied it but written in here, generalizing the stuff that gets repeated in other Management classes.
If you have any other suggestions, as to the code itself, feel free to write that.
These methods are hard to test because they're doing too much. You have input, output to files, and data modifications.
Let's look at this method:
protected X search() {
// Both generic methods.
Integer uuid = enterInteger("ID");
return (X) find(uuid, xes);
}
Why do you call enterInteger when you could pass the desired ID into the method as a parameter? Let the client tell your class which ID to search for. Now the search is doing one thing: looking up a reference in the map.
I think that naming a class X gives no information whatsoever about what it's for. I'd prefer something that gives me a hint - better readability. You abstract all information out of the code with this naming scheme. Good names matter. Think harder about this one.
Your XManagement class looks like a simplistic in-memory database. Have you thought about using something that would allow you to use SQL? Maybe H2 would be a better choice. If this class were interface based you could swap out the implementation and clients would not have to change.
A better design would partition responsibility out to separate classes. For example, your data object could be accompanied by an interface-based persistence tier that would handle searches, updates, persistence, etc.
When I find that methods are too hard to test, it's usually a sign that the class needs to be redesigned. Hard to test is the same thing as hard to use for clients.
I'd replace your XManagement class with an interface:
package persistence;
public interface Repository<K, V> {
List<V> find();
V find(K id);
List<V> find(Predicate<V> filter);
void save(V v);
void update(V v);
void delete(K id);
void delete(V v);
}
You'll have an instance for each one of your Shows, Performances, Tickets, Users, etc.
package persistence;
public class ShowRepository implements Repository<Integer, Show> {
// TODO: You'll need a constructor and a Map for Shows.
public List<Show> find() { // the rest for you }
public Show find(Integer id) { // the rest for you }
public List<Show> find(Predicate<Show> filter) { // the rest for you }
public void save(Show v) { // the rest for you }
public void update(Show v) { // the rest for you }
public void delete(Integer id) { // the rest for you }
public void delete(Show v) { // the rest for you }
}
Much better than your X, in my opinion.
If you write your class using my interface there won't be any console interaction in those classes. Everything it needs is passed in by callers.
You can create separate concrete implementations for an in-memory cache, a relational or NoSQL database that each implement this interface.
You need to redesign your code as current implementation is untestable. I suggest following steps:
break your code to more cohesive classes;
extract interfaces;
use dependency injection for provided classes;
use parametrized methods;
After that you will be able to test your class with mocked dependencies or fake objects. Check out SOLID principles as if you follow them your code will be testable and maintanable.
You question is rather broad.
So, I will focus on the essential.
1) How to test void methods ?
A void method doesn't return any result but it creates side effect on the underlying object/system.
So you have to assert that the void method does what it is designed to do by asserting that the expected side effect is effective.
For example your add() method adds the object in the HashTable (you should rather use a HashMap or a ConcurrentHashMap if you have race conditions), so you should check that the object was correctly added.
You could for example have a search() method that return an object if it is contained. And by using it you could check if the object was added :
X x = ...;
xManagement.add(x);
X actualX = xManagement.search(x.getId());
assertEquals(x, actualX)
To do it, you have to make evolve your actual class that actually doesn't provide a simple retrieval method.
2) How to test classes that have dependencies with other classes ?
Unit tests of a class should be done in isolation of other classes.
So if YManagement methods have to invoke methods of XManagement, you should mock XManagement dependency and record a behavior for it.
Don't test twice the same thing.
I have a problem. So, assume there is this class native to the JRE with 100+ methods:
class HundredMethods {
public void method1(int) {
}
public void method2(int) {
}
... (98 more methods)
}
and I want to alter the arguments of 5 of those methods. Specifically, integers to doubles. and add an extra double argumentMy current solution involves a wrapper class that:-A: Provides direct access to the original class
-B: Has five methods that "translate" double arguments (with some extra inputs) into the integer arguments of the original. So:
class WrapperMethods{
public HundredMethods original = (assigned at constructor)
public void method1(double,double(extra)) {
int i = (assigned a value in "code" below)
this.original.method1(i);
}
}
Is there another lightweight solution to both changing and adding arguments to a few methods in a "heavy" class besides the one above? In terms of actually implementing this solution in my code, I've found that it can get messy when a user doesn't know what methods the wrapper class changes. In fact, I have a roughly 250+ method class that I'm changing 25 methods of, so the bigger the class, the messier my code becomes. Considering that I want to publish my code as public, someone would have to look up what methods the wrapper changes every time they wanted to use the wrapper.
Thanks!
You can make a subclass and add in 2 methods for each of the five methods that you want to modify. One that takes a double, that does your logic and does a super. invocation to the original method, and one that takes an int and makes sure that it does the same thing as when you pass in a double.
All the other 95 methods will still be accessible through your subclass as normal.
class WrapperMethods extends HundredMethods {
public void method1(double d) {
int i = (assigned a value in "code" below)
super.method1(i);
}
public void method1(int i) {
// Make sure that any calls that happen to pass in an integer,
// also go by your logic.
this.method1((double)i);
}
}
This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 6 years ago.
I read this answer about unit-test a wrapper method. In following code:
public static Object methodA(Object arg) {
if (arg == null) {
return null;
} else {
return methodB();
}
}
It looks reasonable that I don't need to test all functionality in methodB(), just test 2 cases where arg is null and not because methodB() should be tested already.
However, if methodB() is private method, I should test all functionality that methodB() will provide because according to another answer, private methods are implementation details.
The problem is, if I have 2 methods methodA1() and methodA2() and they all call methodB() like this:
public static MyObject methodA1(int x) {
MyObject obj = new MyObject();
obj.setX(x);
return methodB(obj);
}
public static MyObject methodA2(int y) {
MyObject obj = new MyObject();
obj.setY(y);
return methodB(obj);
}
private static MyObject methodB(MyObject obj) {
// doSomething with obj
return obj;
}
Should I test methodA1() and methodA2() separately? Or I can just test the private method methodB() because methodA1() and methodA2() are just wrapper methods of methodB(), so if methodB() is correctly tested, I won't need to test methodA1() and methodA2() at all.
EDIT:
I wrote separate tests for public methods at first. But the problem is, if there are many variations of the methodA, and some of the functionalities / requirements are shared in some of them, then the code of the test cases will be duplicated. That's why I wonder if I should test private method methodB().
The real problem I met is I have requirement to add a record in database, and there are many different APIs I should provide. For example, I should provide:
MyObject addMale(String name, String job); // fill sex with "Male"
MyObject addStudent(String name, String sex); // fill job with "Student"
And all of them checks the parameter is valid or not, fill the field that is not specified and call the private method to actually insert the record into the database, which is so called methodB().
There are many APIs like this, so if I can only test methodB() with all fields situation, maybe I can reduce the duplication of the test cases, but is that a good practice to do the unit tests like this?
EDIT2:
I know I can test private methods because I used reflection in my other test cases, and I know it can invoke private methods, too. But my question is about in this situation, testing private methods is a proper solution or not.
This is actually a question I've wondered about for awhile, and while it's not necessarily correct, I'll share my opinion.
The main problem is that private methods are hard to test. I did some Googling, and there some tools and techniques that let you access private methods (reflection is the main one I encountered), but they seemed a little convoluted.
But the reason you wrote a private method is because there is another method, a public method, that calls it. So while you can't directly test the private method, you can check its functionality by testing the public method which calls it.
If I were you, I would extensively test methodA1() and methodA2(), ensuring that all the functionality of methodB() is tested by the tests you run on the public methods.
You've received a few opinions why you should write unit tests for methodA1() and methodA2(); you've pushed back on them. You asked the question here; you are clearly looking for some justification for not writing complete unit test for them. Let's see if we can give you the answer you want. ;-)
From what you've added in your edit, it looks like you have a variation on a builder pattern. Eg)
MyObject o = new Builder().setX(1).setY(2).setZ(3).setW(4).build();
How would we test the builder?
Since the builder has 4 attributes, which could be set in any order, there would be 4! = 24 different orderings. A complete test suite would have to include:
#Test public void testXYZW() { ... }
#Test public void testXYWZ() { ... }
// ... 21 more permutations ...
#Test public void testWZYX() { ... }
But is that all? No! Some of those attributes could have default values, so we would have to test those patterns as well. Total orderings is now P(4,4)+P(4,3)+P(4,2)+P(4,1)+P(4,0) = 24+24+12+4+1 = 85 unit test.
#Test public void testXWY() { ... }
#Test public void testWY() { ... }
#Test public void testZ() { ... }
// ... 61 more permutations ordering
And this only tests each permutation of X, Y, Z, W attributes with one test value per attribute per test. It is clearly unwieldy to write an exhaustive set of tests for every possible combination and permutation.
The designer of the builder class would understand that the permutation of the attribute settings does not affect the resulting construction; writing tests for permutations of the order does not actually increase the test coverage. Tests for omitted attributes are useful, as they test the default values. Testing of different combinations of the omitted attributes again would not increase the test coverage. So, after careful thought, only two tests might be required:
#Test
public void testXYZW() {
MyObject o = new Builder().setX(1).setY(2).setZ(3).setW(4).build();
assertThat(o.wasBuiltProperly());
}
#Test void testDefaults() {
MyObject o = new Builder().build();
assertThat(o.wasBuiltProperlyFromDefaults());
}
If proper, complete testing of methodB() is being done, then you could safely get away with testing only the validation of inputs in methodA1() and methodA2().
#Test void testMethodA1Professor() {
MyObject o = methodA1("professor");
assertThat(o.wasBuiltProperlyWithProfessor());
}
#Test void testMethodA1WithNull() {
MyObject o = methodA1(null);
assertThat(o.wasBuiltProperlyWithNull());
}
Oftentimes, when a private method is used by multiple methods inside a class, there's a distinct concept lurking behind it. It may deserve to have its own class.
it should not be used outside of the class
There are a few ways you could extract methodB to its own class and not make it available as part of your public API :
Nest it inside the class that uses it and give it a restricted scope
Put it in another module at a lower level. Make that module available from your API but not from the clients.
Alright, so I have a driver class and an arraylist (as you can probably guess).
My arraylist is full of strings and I'm accessing it through a getter that I've created in my other class.
It says that "The static method getMouseList() from the type Desktop should be accessed in a static way". How should I go about fixing this? Do you see any other errors?
Thanks to everyone who can help!
So here's my code:
Class:
static ArrayList <String> Strings;
public static void main(String[] args) {
Strings = new ArrayList <String>();
Strings.add("goodbye");
Strings.add("hi");
Strings.add("hello");
}
public static ArrayList<String> getStrings() {
return Strings;
}
Driver class:
Desktop test4 = new Desktop();
System.out.println(test4.getStrings());
Since it's static, it belongs to its class, not to a class instance. Thus, you need to access it using the class: Desktop.getStrings()
UPDATE
I'd need to see more of your code to exactly explain what's going on. So, I'll try to explain on what I imagine is your code. Please note that Java programs start from one main method. Depending on how you execute your program, one of them is going to be invoked, the others will not.
In any case, one way would be to create another static method in Desktop and move the initialization code from main to that method, such as:
public static void initializeStrings(){
Strings = new ArrayList <String>();
Strings.add("goodbye");
Strings.add("hi");
Strings.add("hello");
}
Then, make sure that you call that method, via Desktop.initializeStings(); before trying to access the Strings array (for example in the start of the actual main method of your program.
EDIT 2:
OK, so your main should now look something like this:
public static void main(String[] args) {
Desktop.initializeStrings();
Driver.doSomething();
}
and your Driver's method (inside Driver class):
public static void doSomething() {
//some code
//strings are initialized and will get printed
System.out.println(Desktop.getStrings());
}
That should give you a hint on how to move forward. On a side note, all this staticness is hindering the Object oriented nature of Java. I would suggest a tutorial in Java's object oriented programming model: https://docs.oracle.com/javase/tutorial/java/index.html
I'm a bit of a novice with java and I would appreciate some clarification on when static class variables need to initialized. It a bit much to insert the code I have, so let me break it down to the essential elements. I have an object that performs a particular task. This task requires a number of parameters to be set. These parameters would ideally be static as any instance of the class would use the same parameters. The object is basically a robot that automates a task. The first instance of the robot must be "trained" to do the task (guided by user input). In this "training" it learns a few key parameters and, from those, calculates others that are needed (via a private method). The key parameters are then saved to file to be used by other instances and with subsequent runs of the program (i.e. training is done once only).
The code is structured something like this...
public class Master {
static int[] keyPara;
static int[] otherPara;
public Master() {
/* some defining stuff */
}
void doGuidedTask() {
/* some stuff that calls private methods, etc */
}
void doTask() {
/* some stuff that calls private methods etc */
}
void calcOtherPara() {
/* method to calculate other parameters given key parameters */
}
void saveKeyPara() {
/* method to save key parameters to File */
}
}
The question is what is the proper/best way to initialize these parameters in code? keyPara are determined by implementing the doGuidedTask method, and otherPara are found using the calcOtherPara method. After a single implementation of doGuidedTask, saveKeyPara can be invoked to save them to file and can be read in for subsequent runs of the application program.
I could use a static initialization block: test if the file exists, if so load the key parameters. Not sure if this is allowed because it will require the use of the calcOtherPara method to determine the other parameters i.e. its using a class method in the initialization. Even the read in keyPara would be best implemented as a method (with an eye for future development of the code). The same problem arises if I use the same approach in the constructor - I read elsewhere in the forum that using methods within the constructor is not recommended (not sure I understood why exactly).
I read the tutorial on static variables but it really was not clear to me exactly when they need to be defined and what I should be doing in this case. Any advice here would be appreciated.
public class Master {
static boolean initialised=false;
static int[] keyPara;
static int[] otherPara;
public void doTask() {
if (!initialised)
{
boolean filefound=false;
// put here code to check if your saved file exists
if(filefound)
{
loadkeyfile();
calcOtherPara();
initialised=true;
doAutomatedTask();
} else {
doGuidedTask();
saveKeyPara();
calcOtherPara();
initialised=true;
}
} else {
doAutomatedTask();
}
}
private void doAutomatedTask() {
// put your non-interactive version here
}
}
You should use a static method to initialize static variables.
You can call this static method from the static initializer of the class.
static {
staticMethodThatInitializesStaticMembers ();
}
It appears that are trying to implement something before your object model design is complete. You may have the following objects: Robot (the thing that performs a task); Task (the thing to be performed); TaskStrategy (how to perform the task .. the item you talk about having guided and calculated parameters). You will need to determine whether your task strategies are by task or by robot, and including a reference to a TaskStrategy object in the appropriate class. You may want a TaskStrategyLibrary that handles the task strategies from initial creation through successive learning cycle. With a factory class you can get the appropriate task strategy for a robot (strategy = TaskStrategyLibrary.getStrategy(Robot, Task); and have the TaskStrategy class handle "parameter" changes and update of base strategy.
For this example, I would recommend initializing them when you declare them. So for example, you'd do this:
static int[] keyPara = {1, 2, 3, 4}; //put your array here
static int[] otherPara = {1, 2, 3, 4}; //put a different (or the same) array here