I'd like to have a reflection-like solution for displaying the methods which are called.
Example:
public class Foo {
public void bar() {
new Y().x();
}
}
public class Y {
public void x() {
}
}
public class Main {
public static void main(String[] args) {
// SETTING UP THE MAGIC
new Foo().bar();
new Y().x();
}
}
The output should be:
1. Foo.bar
1.2 Y.x
2. Y.x
Optimally there could be an event handler which would be fired every time a method is called(and some info could be passed as a parameter).
PS: I don't want to use this in a production environment, I only need this for displaying output in a skeleton app without dummy copy-paste.
I would use aspectj to define an aspect which writes log messages for every method call. You can find an example here: Tracing Java Method Execution with AspectJ. or here: Logging with AspectJ
The advantage of this solution is that you don't have to make any changes on your code. You will need some time to get into aspectj, but it meets your requirement very well.
You would have to build a profiler agent if you wanted to achieve this without having to pollute your code.
Take a look at this article, it shows you how to do it. Specifically, look at profiling aspects lower in that article.
Listing 2 is a profiling aspect that can be used to output the class name, method name, and a timestamp every time the JVM enters or leaves a method.
Related
I am writing a test for a class which has a setup
class A
{
private String name;
public String getName()
{
return "Hello "+ name;
}
public void setName(String name)
{
this.name = name;
}
My test class
TestA
A a = new A();
{
#Before
void setup()
{
a.setName("Jack");
}
#Test
public void testTom()
{
assert(a.getString(), "Hello Tom");
}
#Test
public void testJack()
{
assert(a.getString(), "Hello Jack");
}
How to change the value of name between the methods since #Before calls for every test method?
ie) if execute testJack then the output should be Hello Jack.
I tried with #Parameters but before that setup is getting called so i couln't acheive this functionality.
First, the code:
#Before
void setup()
{
A a = new A();
a.setName("Jack");
}
Doesn't do anything which the Tests can see. You're creating a local variable a which goes out of scope almost immediately.
#Before is designed to set and reset a state or context before each Test is run. It doesn't vary unless something it relies on changes between invocations.
You could create a Stack as an instance variable and pre-populate it in a #BeforeClass method, and have #Before pop a value to be used every time it's called. This is unadvisable as it assumes that the Tests will be run in some particular order. It's much cleaner and clearer to just declare different values inside each Test.
There is simply no point in doing that; as your real problem is rooted in your statement "Just assume the scenario of 30 lines of code in setup".
If you need 30 lines of setup code, then your code under test is not following the "single responsibility principle" and doing way too many different things.
Of course, you can turn to "data driven" testing to somehow get there (see here for example); but that would be fixing the Y side of an XY problem.
I know, it sounds harsh: but you better step back; and learn about doing reasonable OO design (for example based on SOLID). Then you rework your code to not need 30 lines of setup code.
You see, if your code is so hard to test; I guarantee you: it is also hard to understand, and will be close to impossible to maintain/enhance over time. And beyond that: it will be even hard to get your code to be "correct" in the first place.
Long story short: have a look in these videos and improve your design skills.
In my java code there is class A that has the following line:
Process localProcess = Runtime.getRuntime().exec(myString);
where myString is user supplied input and is passed to exec() at runtime.
Also there is a public method doSomething() in class A.
Can I somehow invoke doSomething() (through reflection, jdwp etc.) using exec() at runtime ?
Starting a new JVM just to call a single method? First, that would be really slow. And second, it would be highly unnecessary!
Reflection is what you want I guess. Here's some sample code.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Class<Main> c = Main.class; // First get the class
try {
Method method = c.getMethod("doSomething"); // get the method by its name
method.invoke(new Main()); // call it on a new instance of Main
} catch (NoSuchMethodException e) {
System.out.println("Method is not found"); // print something when the method is not found
}
}
public void doSomething() {
System.out.println("I have done something!");
}
}
That would mean starting a whole new JVM just to make a method call.
If you are already "within" class A; what prevents you from calling doSomething() directly? Probably: only your lack of skills. If so, then work on your skills; and don't go for the next best solution you heard somebody mention how things might be done!
In essence: a self-claimed geek should always understand each and any concept he is using in his programs. If you want to use reflection, then study what reflection is about.
And please note: letting your users pass in arbitrary strings to have them executed, is a huge security NO GO. You should have mentioned in your question that you want to do this on purpose; and that you are fully aware of the potential consequences of doing so!
EDIT; given your latest comments.
In this case, a solution could be as simple as:
A) you write a new class, like
public class Invoker {
public static void main(String[] args) {
A.doSomething();
or if doSomething isn't static, you will need
A someA = new A( ... however you can create instances of A
A.doSomething()
B) Compile that, and then you can simply send a command like
java -cp WHATEVER Invoker
into your existing application. Of course, you have to work out the details; like providing a valid classpath to that call to java (that classpath has to include the location where Invoker.class lives; and of course A.class; and all of the dependencies that A has).
But keep in mind: doSomething() is executed in the scope of a different JVM. That means that most likely, it will not at all affect class A in that JVM where you trigger the call to exec!
I want to inject some code through annotations in java.
The plan is I have two methods beginAction() and endAction(). I want to annotate a method such that before executing the statements in the method the beginAction() will be put and after finishing executing them the endAction() will be put automatically. Is it possible. If yes please suggest me how to do.
#MyAnnotation
public void myMethod(){
// Statement 1;
// Statement 2;
}
At runtime the beginAction() and endAction() should be injected in the method through the annotation. That is it should become like the following at runtime.
public void myMethod{
beginAction();
// Statement 1;
// Statement 2;
endAction();
}
It looks like you need aspects. AspectJ is the most popular library in this case. You can read more about it here: https://eclipse.org/aspectj/docs.php
And here's the example of such aspect in use:
Class with intercepted method:
public class YourClass {
public void yourMethod() {
// Method's code
}
}
Aspect itself:
#Aspect
public class LoggingAspect {
#Around("execution(* your.package.YourClass.yourMethod(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Do something before YourClass.yourMethod");
joinPoint.proceed(); //continue on the intercepted method
System.out.println("Do something after YourClass.yourMethod");
}
}
You can't do it using just plain Java. However, there is a Java-like language that does allow this. It's called Xtend. It compiles to Java, not bytecode, so it benefits from all the wonderful things your Java compiler does.
It started life as an Eclipse project, but is now also available for IntelliJ.
One of its many features is a thing called "Active Annotations". They do exactly what you're asking for: they allow you to participate in the code generation process, so you can insert your beginAction() and endAction() methods as you want.
See http://www.eclipse.org/xtend/documentation/204_activeannotations.html for more info on Active Annotations.
I am working on the Junit test case and the grading scheme is based on the coverage of the code.
I meet a problem about some #override method inside a method because it seems like I can not call that method.
Just like the example below.
public void showFollowersList(PagableResponseList<User> followers) {
m_itemList.addListener(SWT.Resize, new Listener() {
#Override
public void handleEvent(Event arg0) {
m_itemList.setLayoutData(new RowData(m_itemList.getBounds().width,
m_itemList.getBounds().height));
m_rightFrame.layout();
m_rightFrame.pack();
}
});
}
addMouseTrackListener(new MouseTrackListener() {
#Override
public void mouseHover(MouseEvent arg0) {
}
#Override
public void mouseExit(MouseEvent arg0) {
Rectangle rect = HoverClickableComposite.this.getClientArea();
if (!m_clicked && !rect.contains(arg0.x, arg0.y)) {
setBackground(m_origColor);
}
}
How can I call or cover the method like handleEvent , mouseExit and mouseHover ?
If it helps, I think someone's done a very good job at making showFollowersList un-testable. Was that deliberate?
If so, the correct answer might not actually be a set of test code, but a very low coverage score and a list of recommendations for changing the class to make it more testable...
The only way to test it at the moment would be to set things up, poke it, and check what happens.
And that would only work if you can cause a handleEvent call to be fired on your object, and certain methods were available on the class:getList, getListenerCount, etc. Then, something like:
testObject.showFollowersList(followers);
// All that method does is add listener. So check that listener got added
assertEquals(1, testObject.getList().getListenerCount());
// Now check that inner handlers behave correctly
testObject.getList().fireEvent();
// This should have created a new RowData in the list
assertNotNull(testObject.getList().getLayoutData());
But if you don't have those methods available, then it's definitely not a good idea to add them and expose the List just for the sake of Unit Testing.
Another problem is the GUI. Your Unit Tests won't have a GUI. So, your m_rightFrame will probably be null (and even if it isn't, the underlying AWT classes will be).
It is not a method 'inside a method', it is a method of an anonymous class.
Usually, with SWT or Swing programming, it is the functional (business) aspect of the code that requires much test coverage, and not the scaffolding (handlers etc.)
However, if this is what is required, there are at least two options -
Do not use anonymous inner classes for the handlers - give them names in the same package.
Use a mocking framework like Powermock with JUnit and pass mocked SWT event objects to invoke handlers so that you have coverage.
I have no control of where System.getProperty is called in the project. I want to log some information in the console whenever System.getProperty("SomeProperty"); is called.
How to achieve this.
You could try creating a java.lang.SecurityManager that throws an exception or prints some stuff out in the checkPropertyAccess(String) method. It gets called when something accesses System properties.
More info about Security Managers:
http://docs.oracle.com/javase/tutorial/essential/environment/security.html
http://java.sun.com/developer/onlineTraining/Programming/JDCBook/signed2.html
You would like to use AspectJ and its pointcut. Take a look here for more.
Here is an example adapted from the tutorial mentioned above.
#Aspect
public class Foo {
#Pointcut("call(* java.lang.System.getProperty(..))")
void anyUtilityCall() {
// do whatever you need
}
}