Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing asynchronous code with JUnit

I want to test some code that relies on a network transmission. The code makes a request and supplies a callback - when the request completes, the callback is fired. I'd like to mock out the network transmission, and use Thread.sleep to simulate some latency... but of course that will make the whole test pause.

So far I've been making new threads and using CountDownLatches throughout the test to stop the test from ending before the callback is fired. My mock network object makes a new thread, sleeps on that thread, and then fires the callback. That's actually working pretty well, but the problem is that any assertion errors in the callback are not reported to the original junit thread - instead, I'm getting exception text on the console, where it's much harder to understand and use.

I'm hoping there's either:

  1. A way to pipe assertEquals output from spawned threads into the main JUnit output collector, or
  2. A totally different and better way to test threaded code in JUnit, or
  3. Some way to simulate asynchronous code in a single thread

Thanks for any ideas!

like image 395
Riley Lark Avatar asked Dec 11 '11 20:12

Riley Lark


People also ask

How do you test asynchronous methods?

This illustrates the first lesson from the async/await conceptual model: To test an asynchronous method's behavior, you must observe the task it returns. The best way to do this is to await the task returned from the method under test.

How do you test async in Jasmine?

You can check on the spied on function in . then of the async call. This is where you can use toHaveBeenCalled or toHaveBeenCalledWith to see if it was called. You should also check if the result of the promise is the expected output you want to see via the toEqual matcher.


1 Answers

When I had to implement asynchronous mechanism similar to yours I created abstract class AsyncTestCase that holds test error and provides special method waitForCallback(). When asynchronous task finds error in expected results it puts the error into this variable. The setter calls notify() on object that is used by waitForCallback(). So, when callback arrives it immediately causes test to awake. Then I can call all assertions including that one that was stored by asynchronous task.

And do not forget to put timeout on your tests to prevent them from sleeping forever:

@Test(timeout=10000)
public void mytest() {
    callAsyncTask();
    waitForAsyncTask();       // from base class
    assertAsyncTaskResult();  // from base class
}
like image 63
AlexR Avatar answered Oct 24 '22 19:10

AlexR