简体   繁体   中英

GWTTestCase: JUnit Assertions within callback raises JavaScriptException

So if I call any JUnit assertion which fails from inside a callback method I get this exception:

Mar 12, 2012 11:24:41 AM 

com.gargoylesoftware.htmlunit.javascript.background.JavaScriptJobManagerImpl runJob
SEVERE: Job run failed with unexpected RuntimeException: [object Class JavaObject] (injected script#14)
net.sourceforge.htmlunit.corejs.javascript.JavaScriptException: [object Class JavaObject] (injected script#14)
    at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpretLoop(Interpreter.java:1062)
    at script(injected script:14)
    at net.sourceforge.htmlunit.corejs.javascript.Interpreter.interpret(Interpreter.java:845)
    at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:164)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.doTopCall(ContextFactory.java:429)
    at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.doTopCall(HtmlUnitContextFactory.java:269)
    at net.sourceforge.htmlunit.corejs.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3162)
    at net.sourceforge.htmlunit.corejs.javascript.InterpretedFunction.call(InterpretedFunction.java:162)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.callFunction(JavaScriptEngine.java:559)
    at com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequest.setState(XMLHttpRequest.java:181)
    at com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequest.doSend(XMLHttpRequest.java:525)
    at com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequest.access$000(XMLHttpRequest.java:64)
    at com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequest$1.run(XMLHttpRequest.java:461)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:537)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:538)
    at com.gargoylesoftware.htmlunit.javascript.host.xml.XMLHttpRequest$2.run(XMLHttpRequest.java:467)
    at com.gargoylesoftware.htmlunit.javascript.background.JavaScriptJobManagerImpl.runJob(JavaScriptJobManagerImpl.java:226)
    at com.gargoylesoftware.htmlunit.javascript.background.JavaScriptJobManagerImpl.runSingleJob(JavaScriptJobManagerImpl.java:307)
    at com.gargoylesoftware.htmlunit.javascript.background.JavaScriptExecutor.run(JavaScriptExecutor.java:182)
    at java.lang.Thread.run(Thread.java:722)

A simple test that produces this:

public void testSimple() {
    MyPrgrmServiceAsync serv = GWT.create(MyPrgrmService.class);
    serv.search("some query", new AsyncCallback<SearchResult>() {
        public void onSuccess(SearchResult sr) {
            fail();
        }

        public void onFailure(Throwable caught) {
            fail(caught.toString());
        }
    });

    delayTestFinish(60000);
}

When this test is run, it "passes" as far as the JUnit Runner is concerned with the green bar displayed in Eclipse, but obviously it's supposed to fail. The only indication that anything went wrong is the exception in the console. If I move the fail() outside the callback, it fails normally and indicates so. Additionally, assertions that resolve to true behave normally, so it seems the test simply doesn't know how to detect failures when they arise from within anonymous classes. Is there something I'm not understanding correctly about how to use JUnit assertions within callbacks/anonymous classes with respect to GWTTestCase?

Your basic understanding seems to be correct - delayTestFinish 's mandate is to not allow the test to pass unless finishTest() is called within the number of milliseconds given (60 seconds, in your case). There is no need to call finishTest() in either callback method, as fail will throw an exception (if the code even gets that far).

Are you sure the test is completing successfully? As written, if something is misconfigured and the call never goes through to the server, or the server never returns, neither fail nor finishTest cannot be called, so the test method cannot pass. Make sure you wait the full 60 seconds before accepting the result as 'passed' - if finishTest is never called, then either the test method won't be considered as complete, or it should be considered a failure.

That said, the exception is useful to look at - this is from within the emulated browser - htmlunit - and this exception is something going wrong in the 'browser'. From the short trace and no other log statements it is hard to say what exactly is going wrong. You might also consider running this in a real browser to see if any more useful error shows up - check out http://code.google.com/webtoolkit/doc/latest/DevGuideTestingRemoteTesting.html for how to make the test run from a regular browser, in either dev or prod mode.

One other thought might be to register an uncaught exception handler with GWT to see what that picks up - it is possible that some other exception is killing the test, and somehow doing it in such a way as to prevent delayTestFinish from functioning correctly (though I've never heard of such a thing).

GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
  public void onUncaughtException(Throwable e) {
    fail(e.getMessage());
  }
});

The problem was I was calling finishTest() in my gwtSetUp(). I was running some initialization code there which was an asynchronous method, and wanted to make sure it finished before the actual test code, but turns out it was just finishing the test before anything was actually tested. Moral of the story: Don't be silly about your finishTest() placement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM