0

I'm having problems debugging a JUnit testcase. I'm using Java v6 and JUnit Framework v3.8.2.

I invoke jdb like this:

jdb junit.textui.TestRunner MyTest

The problem is that I don't know the name of the object TestRunner creates from my TestCase class. For example, I'd like to print the return value of a method, but how do I call the method, when I don't know the name of the object?

Edit: The exception occurs at line 45, this is the call stack that I get when executing "where" in jdb:

[1] MyTest.test1 (MyTest.java:44)
[2] sun.reflect.NativeMethodAccessorImpl.invoke0 (native method)
[3] sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57)
[4] sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
[5] java.lang.reflect.Method.invoke (Method.java:616)
[6] junit.framework.TestCase.runTest (TestCase.java:164)
[7] junit.framework.TestCase.runBare (TestCase.java:130)
[8] junit.framework.TestResult$1.protect (TestResult.java:106)
[9] junit.framework.TestResult.runProtected (TestResult.java:124)
[10] junit.framework.TestResult.run (TestResult.java:109)
[11] junit.framework.TestCase.run (TestCase.java:120)
[12] junit.framework.TestSuite.runTest (TestSuite.java:230)
[13] junit.framework.TestSuite.run (TestSuite.java:225)
[14] junit.textui.TestRunner.doRun (TestRunner.java:121)
[15] junit.textui.TestRunner.start (TestRunner.java:185)
[16] junit.textui.TestRunner.main (TestRunner.java:143)

Edit2: I mixed things up, I know the name of the object I want to print a method of, but it still doesn't work. I wrote a small test case and class to explain the exact problem.

This is the test case:

import junit.framework.TestCase;

public class TestJUnit extends TestCase {

    public void test1() {
        try {
            JUnitTestClass mtc = new JUnitTestClass();
            assertTrue(mtc.method1() == 1);
            assertTrue(mtc.method1() == 2);
        } catch (Exception exc) {
            fail(exc.getMessage());
        }
    }
}

And this is the class that is tested:

public class JUnitTestClass {

    private int att1 = 0;

    public int method1() {
        this.att1 += 1;
        return this.att1;
    }
}

Then I run the debugger like so:

bash-4.2$ jdb -classpath $CLASSPATH junit.textui.TestRunner TestJUnit
Initializing jdb ...
> stop at TestJUnit:8
Deferring breakpoint TestJUnit:8.
It will be set after the class is loaded.
> run
run junit.textui.TestRunner TestJUnit
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint TestJUnit:8
.
Breakpoint hit: "thread=main", TestJUnit.test1(), line=8 bci=8
8                assertTrue(mtc.method1() == 1);

main[1] print mtc.method1()
com.sun.tools.example.debug.expr.ParseException: Name unknown: mtc.method1
mtc.method1() = null
main[1] dump mtc
com.sun.tools.example.debug.expr.ParseException: Name unknown: mtc
mtc = null

When I try to print the method or dump the object, I get "Name unknown".

Edit3: I simply forgot to use -g when using javac, sorry.

bug
  • 515
  • 1
  • 5
  • 17
  • Could you clarify what you mean by object name? In JDB you can set breakpoints in classes, not objects. Is there any reason you cannot use Eclipse or Netbeans? – allprog Dec 14 '12 at 12:04
  • No, but I'd like to do it over the command line. I can set break points inside my test case class just fine, but that class is initalized by the JUnit test runner, which means that an object is created and I don't know the name of that object. – bug Dec 14 '12 at 12:33
  • JUnit instantiates your class with the "MyTest()" constructor and invokes the "test1" method on it. If you set a breakpoint in line 45, then the execution will stop there. I can't see why you need the name of the object. And I still don't really understand what "name of the object" means, Java objects are addressed by references. Can you share the source code? We may better understand your use case. Also it may be better if you first tried to debug with some IDE. Or at least shared the commands you issue in the command line. – allprog Dec 14 '12 at 13:54
  • You're right, sorry I mixed things up. I think I know the name of the object, but I get "Name unknown" whenever I try to access it within jdb. – bug Dec 14 '12 at 14:22

2 Answers2

1

Sorry folks, I'm new to all of this and I made a silly mistake. I forgot to use the -g command when calling javac to generate my test case class file. It works now.

bug
  • 515
  • 1
  • 5
  • 17
  • Nice example for running JUnit tests from the command line. Just a small suggestion: Instead of fail, just throw an exception. In my practice I use fail() only in cases when the code should not run in some branch and I don't have an exception to throw. The way you use it will remove the stack trace which is vital in such cases. – allprog Dec 14 '12 at 20:13
0

Can you set a breakpoint in one of your actual test methods, and then take a look at the call stack when it breaks, and step up into the actual JUnit code?

This would probably be easiest with a visual debugger. It also assumes that the JUnit instance you're running was built with debugging support. You won't get any symbolic information otherwise.

Omaha
  • 2,262
  • 15
  • 18