I am using Mockito together to JUnit to implement unit tests for a class in an Android project.The problem is that I call Mockito.verify in two consequent tests where the tests are exactly same (to make sure that I am using Mockito correctly) but the interesting thing is that verify in second test always fails.I suspect that some operations need to be done before each test using #before annotation or so, that I have missed.Here are some code snippet about what I am doing.
I use Android Studio 3.4.1, Mockito 2.7.22 and JUnit 4.12.
#Test
public void test_onStart_do_nothing() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
verify(mockedZConnection, times(1)).connect();
}
#Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Line above is the line that error message points to!
verify(mockedZConnection, times(1)).connect();
}
Here comes the function under test
public void initConnection(ZConnection connection) {
Log.d(TAG,"initConnection()");
if (mConnection == null) {
mConnection = connection;
}
if (!mActive) {
mActive = true;
if (mThread == null || !mThread.isAlive()) {
mThread = new Thread(new Runnable() {
#Override
public void run() {
// The code here runs in a background thread.
Looper.prepare();
mTHandler = new Handler();
try {
mConnection.connect();
} catch (IOException e) {
Intent i = null;
i = new Intent(ZConnectionService.UI_NOTCONNECTED);
i.setPackage(getApplicationContext().getPackageName());
getApplicationContext().sendBroadcast(i);
e.printStackTrace();
// Stop the services all together.
stopSelf();
}
Looper.loop();
}
});
mThread.start();
}
}
}
I expect that both tests should pass without any problem. In fact, both tests are passed when I ran them individually, but they fail when I run the whole suite and the error is:
Wanted but not invoked:
mockedZinkConnection.connect();
-> at com.app.z.ZConnectionServiceUnitTest.test_onStart_throw_IO_exceptioon(ZConnectionServiceUnitTest.java:207)
Actually, there were zero interactions with this mock.
I think the issue is a multithreading one.
When you call initConnection, it calls mConnection.connect() in a Thread
The problem you are having is that this Thread takes some time to complete and you end up calling verify(mockedZConnection, times(1)).connect(); before the Thread actually reached the connect() call.
A way to make sure about it is to join the Thread after you start it, it will wait until the Thread has finished before continuing:
mThread.start();
try {
mThread.join();
} catch (InterruptedException i) {
i.printStackTrace();
}
Now both tests should work.
This of course is not acceptable in the code, because it negated the use of a Thread. You will need an other way to test it.
A way I can think of would be to wait for the Thread to complete in your test before checking the mock:
#Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Wait for the Thread to complete
while(zConnectionService.mThread.isAlive()) {
Thread.sleep(100);
}
verify(mockedZConnection, times(1)).connect();
}
Tried and it works fine for me. Not sure it is a best practice though as you need to make public some internals of your class, which violates encapsulation
maybe having a package protected isThreadAlive() method on your ZConnectionService class could be acceptable
boolean isThreadAlive() {
return mThread.isAlive();
}
and the loop in the test
while(zConnectionService.isThreadAlive()) {
Thread.sleep(100);
}
Related
This is the method I'm trying to mock:
#VisibleForTesting
public List<Row> processRows2(CompletableFuture future) {
List<Row> rows2 = new ArrayList<>();
try {
DefaultAsyncResultSet beep = (DefaultAsyncResultSet) future.get();
for (Row b : beep.currentPage()) {
rows2.add(b);
}
}
catch (ExecutionException | InterruptedException e) {
LOGGER.error(e);
LOGGER.error(e.getStackTrace());
throw new RuntimeException(e.getMessage() + " - Check thread pool resources are enough, may be too many queries in queue");
}
return rows2;
}
The problem is that when I try to test it with this (currently just trying to get it to run all the way to either success or failure):
#Test
public void processRows2test() {
FeatureDaoImpl gar = new FeatureDaoImpl(connection);
CompletableFuture L = new CompletableFuture();
gar.processRows2(L);
}
It hangs endlessly. My guess is that the future.get() is where it's hanging; I'm not sure. But I'm not sure how to mock that. I've tried this:
#Mock
private CompletableFuture mockFutures;
#Before
public void setUp() {
try {
Mockito.when(mockFutures.get()).thenReturn((AsyncResultSet) mockResultSetFuture);
}
catch (Exception e) {
}
}
But this I feel is not correct. The try catch is because it yells at me about unhandled exceptions on the get(), so I don't know how to get around that.
I have also now tried this:
#Mock
final CompletableFuture<List<String>> mockedFuture = Mockito.mock(CompletableFuture.class);
With the following in the setup:
Mockito.doReturn(new ArrayList<Row>()).when(mockedFuture).get();
But it still hangs endlessly.
I've seen these:
How to mock completion of a CompletableFuture in Mockito
This one I don't understand what exactly it's trying to get me to do, and doesn't feel super applicable, because it's not a get method. I saw some examples here that have .get() in them... but none were mocked methods unfortunately, they were gets in the test itself: https://www.javatips.net/api/java.util.concurrent.completablefuture
EDIT: the code runs. It returns results. So it isn't that the actual method isn't returning a value - I know it does this, it's doing it in QA right now.
Your current CompletableFuture is not completed, so the .get() method hangs waiting for async completion that will never happen. You can use CompletableFuture.completedFuture(value) to create a CompletableFuture instance that will return the passed value when .get() is called on it.
You can use the CompletableFuture.completedFuture method here
#Test
public void processRows2test() {
FeatureDaoImpl gar = new FeatureDaoImpl(connection);
CompletableFuture L = CompletableFuture.completedFuture(new ArrayList<Row>());
gar.processRows2(L);
}
I have some runnable where one of the parameter is delegator with taskExecutor to execute another runnable:
#Override
public void run() {
try {
doTask(messageId);
} catch (Exception e) {
count++;
if (count < 4) {
delegatedTransactionalAsyncTaskExecutor.execute(this);
} else {
delegatedTransactionalAsyncTaskExecutor.execute(getOnExceedErrorTask(messageId));
}
throw new RuntimeException(e);
}
}
how should I test this ?
It seems that delegatedTransactionalAsyncTaskExecutor is a field in your class.
In order to ensure that you can test it, you have to use dependency injection, like this:
class UnderTest {
private final Whatever delegatedTransactionalAsyncTaskExecutor;
UnderTest(Whatever delegatedTransactionalAsyncTaskExecutor) {
this.delegatedTransactionalAsyncTaskExecutor = delegatedTransactionalAsyncTaskExecutor;
...
And now, you can use mocking frameworks to create objects of that Whatever class. Mocks allow you to specify the method calls you expect to happen; and then, you can verify later on that those calls really took place.
In other words: you prepare a mock; then you invoke run() ... and afterwards you check that those calls you were looking for actually happened. And of course for the whole thing to work, you must be able to inject those mocks into your "class under test".
I've been using Java for a few years, but my thread knowledge is rubbish. I've Googled pretty heavily and found some good information about general use of ProgressMonitorDialog but nothing like my exact circumstances.
I'm currently using a ProgressMonitorDialog as a wrapper around an instance of IRunnableWithProgress, which in turn is a wrapper around a Thread. This works fine but now I'm trying to make the cancel button trigger an interrupt on the running thread, which I can handle to gracefully terminate the operation.
One important thing to note is that I have two plugins; "Data" and "UI". The data plugin contains all of the real work, and must be independent from the UI or any Eclipse plugins. The UI plugin should be as thin as possible.
Here's a distilled version of the code I've got so far.
Data:
public class Data {
public static Thread createThread() {
return new Thread() {
#Override
public void run() {
Thing t = new Thing();
t.operationA();
t.operationB();
t.operationC();
}
}
}
}
UI:
public class UI {
public void doOperation() {
try {
new ProgressMonitorDialog(getShell()).run(true, true, new MyOperation());
}
catch (Exception e) {
e.printStatckTrace();
}
}
public class MyOperation implements IRunnableWithProgress {
#Override
public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
monitor.beginTask("Task", 2);
try {
Thread myThread = Data.createThread();
myThread.start();
monitor.worked(1);
while (myThread.isAlive() && !monitor.isCanceled()) {}
if (monitor.isCanceled()) {
myThread.interrupt();
}
monitor.worked(1);
}
finally {
monitor.done();
}
}
}
}
So when the cancel button is clicked, myThread.interrupt() is called. Now the thread needs to respond to the interrupt. Data.createThread() now looks something like this:
public static Thread createThread() {
return new Thread() {
#Override
public void run() {
Thing t = new Thing();
t.operationA();
if (Thread.currentThread.isInterrupted()) {
// Tidy up
return;
}
t.operationB();
if (Thread.currentThread.isInterrupted()) {
// Tidy up
return;
}
t.operationC();
if (Thread.currentThread.isInterrupted()) {
// Tidy up
return;
}
}
}
}
It might be rather verbose polling the interrupted state like this, but I can't see this causing any problems.
But, what if Thing.operationA() wasn't atomic, and could be interrupted within that function:
public class Thing {
public void operationA() {
atomic1();
// How would I detect and handle a change to the interrupted state here?
atomic2();
}
public void operationB() {
// One atomic operation
}
public void operationC() {
// One atomic operation
}
}
How would I detect and handle a change to the interrupted state between atomic1() and atomic2()? Is it as simple as polling Thread.currentThread.isInterrupted() again? Or will I need to pass around some volatile object to track the interrupted state? Should I be throwing InterruptedException somewhere?
My second question is about tracking and reporting progress. I understand how IProgressMonitor.worked() should be used. As already seen, my Data thread contains 3 operations. Is it possible to pass that information up to the UI so I can track the progress in the ProgressMonitorDialog?
Ideally, something like this:
public static Thread createThread() {
return new Thread() {
#Override
public void run(IProgressMonitor monitor) {
Thing t = new Thing();
t.operationA();
monitor.worked(1);
if (Thread.currentThread.isInterrupted()) {
// Tidy up
return;
}
t.operationB();
monitor.worked(1);
if (Thread.currentThread.isInterrupted()) {
// Tidy up
return;
}
t.operationC();
monitor.worked(1);
if (Thread.currentThread.isInterrupted()) {
// Tidy up
return;
}
}
}
}
However as stated, Data cannot depend on Eclipse and therefore passing the IProgressMonitor doesn't work in this case.
Could I have a variable tracking progress in my thread, and then call something like myThread.getProgress() asynchronously from the UI thread to update the progress bar with new work? I'm not sure how feasible this is (it popped into my head as I was writing this question) so I'll try that next.
Lots of information and question marks in here, sorry if my style is a bit scattered. I could elaborate more if needs be but this is already a wall of text. Any information, advice or ideas appreciated.
Between atomic1() and atomic2() you do need to check for Thread.currentThread.isInterrupted() to cleanup in case of canceling. No need to throw an exception if you handle what is needed.
As for progress tracking, you can create your own listener object in the Data plugin and allow passing it to the thread. the UI will instantiate it and pass it to the thread. this way the Data can pass progress events to the UI without dependencies.
I am writing a Api that executes HTTP Request on a worker thread then call a method of a Callback-Handler when finish.
public class GriklyClient <E,T>{
private final IHttpRequest<E,T> request;
private final ResponseListener<T> response;
protected GriklyClient (IHttpRequest<E,T> request,ResponseListener<T> response)
{
this.request = request;
this.response = response;
}
/**
* Dispatch a thread to process
* HTTP Request.
*/
public void execute ()
{
Runnable thread = new Runnable()
{
public void run()
{
T result = (T) request.execute ();
response.response(result);
}
};
new Thread(thread).start();
}//end execute method
}
This is how a call to the ApI looks like:
Grikly grikly = new Grikly(developerKey);
grikly.addValidUserCredential(email,password);
grikly.fetchUser(1, new ResponseListener<User>() {
public void response(User result) {
// TODO Auto-generated method stub
System.out.println(result);
}
});
The problem I am having is Unit Testing. The Callback Handler is not being called in my Unit Test thus all my Test always pass even when they should fail.
private Grikly grikly = new Grikly (developerKey);
#Test
public void fetchUser ()
{
grikly.fetchUser(1, new ResponseListener<User>() {
public void response(User result) {
Assert.assertNotNull(result);
}
});
}//end fetchUser Test
How can I write a Unit test to test this Api?
Well, I guess your problem here is because your method fetchUser is an asynchonous method rather than a synchonous one which will not return until it have done its job.
So, the calling of grikly.fetchUser(... will return immediately(so does the test method fetchUser() w/o any sign of failure or success), while the 'lonely' thread you create in GriklyClient will keep running and finish its job by calling the callback method response in your new ResponseListener<User> and of course, nobody cares at that time.
IMO, either a CountdownLatch or a more general ReentrantLock with its Condition buddy can save your day. And tutorials talking about these two tools can be easily found using Google. Good luck with that.
EDIT:
On a second thought, if you wanna test the result that got passed to the callback method, it might be necessary to pass(or publish) it from the new thread you create to the test main thread(by save it to a lock guarded or volatile decorated field) and test it in the #Test annotated method, which in your case is the fetchUser().
I'm writing small app and now I discovered a problem.
I need to call one(later maybe two) method (this method loads something and returns the result) without lagging in window of app.
I found classes like Executor or Callable, but I don't understand how to work with those ones.
Can you please post any solution, which helps me?
Thanks for all advices.
Edit: The method MUST return the result. This result depends on parametrs.
Something like this:
public static HtmlPage getPage(String page) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
return webClient.getPage(page);
}
This method works about 8-10 seconds. After execute this method, thread can be stopped. But I need to call the methods every 2 minutes.
Edit: I edited code with this:
public static HtmlPage getPage(final String page) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
Thread thread = new Thread() {
public void run() {
try {
loadedPage = webClient.getPage(page);
} catch (FailingHttpStatusCodeException | IOException e) {
e.printStackTrace();
}
}
};
thread.start();
try {
return loadedPage;
} catch (Exception e) {
return null;
}
}
With this code I get error again (even if I put return null out of catch block).
Since Java 8 you can use shorter form:
new Thread(() -> {
// Insert some method call here.
}).start();
Update:
Also, you could use method reference:
class Example {
public static void main(String[] args){
new Thread(Example::someMethod).start();
}
public static void someMethod(){
// Insert some code here
}
}
You are able to use it when your argument list is the same as in required #FunctionalInterface, e.g. Runnable or Callable.
Update 2:
I strongly recommend utilizing java.util.concurrent.Executors#newSingleThreadExecutor() for executing fire-and-forget tasks.
Example:
Executors
.newSingleThreadExecutor()
.submit(Example::someMethod);
See more: Platform.runLater and Task in JavaFX, Method References.
Firstly, I would recommend looking at the Java Thread Documentation.
With a Thread, you can pass in an interface type called a Runnable. The documentation can be found here. A runnable is an object that has a run method. When you start a thread, it will call whatever code is in the run method of this runnable object. For example:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// Insert some method call here.
}
});
Now, what this means is when you call t.start(), it will run whatever code you need it to without lagging the main thread. This is called an Asynchronous method call, which means that it runs in parallel to any other thread you have open, like your main thread. :)
In Java 8 if there is no parameters required you can use:
new Thread(MyClass::doWork).start();
Or in case of parameters:
new Thread(() -> doWork(someParam))