How do I unit test a method that contains a CompletableFuture?
I tried looking this up, but couldn't quite understand the examples I found. I have a class with a Spring AfterPropertiesSet()
method that calls 2 other methods to spin off asynch calls. I'm at a loss how as to to unit test them. The method startProcessingThread()
looks like this:
void startProcessingThread(executor) {
CompletableFuture.runAsync(() -> {
Path filePath = null;
do {
filePath = retrieveFromFileQueue();
submitFileForProcessing(filePath);
} while (keepRunning);
}, executor)
.handle((theVoid, exception) -> {
if (exception != null) {
LOG.error("Error submitting file for processing: " + exception);
}
return null;
});
}
I don't want to rewrite the CompletableFuture
in the test method (do I?). So I figured I need to call startProcessingThread()
, using Mocks (from Mockito) inside the methods that need them (retrieveFromFileQueue()
and submitFileForProcessing()
). But what about the CompletableFuture
itself? Should I mock that? I'm sorry, but I'm really confused...
java unit-testing
|
show 1 more comment
I tried looking this up, but couldn't quite understand the examples I found. I have a class with a Spring AfterPropertiesSet()
method that calls 2 other methods to spin off asynch calls. I'm at a loss how as to to unit test them. The method startProcessingThread()
looks like this:
void startProcessingThread(executor) {
CompletableFuture.runAsync(() -> {
Path filePath = null;
do {
filePath = retrieveFromFileQueue();
submitFileForProcessing(filePath);
} while (keepRunning);
}, executor)
.handle((theVoid, exception) -> {
if (exception != null) {
LOG.error("Error submitting file for processing: " + exception);
}
return null;
});
}
I don't want to rewrite the CompletableFuture
in the test method (do I?). So I figured I need to call startProcessingThread()
, using Mocks (from Mockito) inside the methods that need them (retrieveFromFileQueue()
and submitFileForProcessing()
). But what about the CompletableFuture
itself? Should I mock that? I'm sorry, but I'm really confused...
java unit-testing
This code does not wait for theCompletableFutur
to finish nor it uses it's result. Why did you choose it in favour to an ordinaryRunnable
?
– Timothy Truckle
Feb 10 '17 at 8:27
You should create the lambda in a different method (or as an class of its own). Then you can mock it and check, that this method runs it (have your test wait a few ms after calling the method), also you can verify the lambdas behavior itself directly.
– Timothy Truckle
Feb 10 '17 at 8:29
Timothy, this code is not my design. I'm not really sure why a CompletableFuture was used. Does it not have any advantages over a Runnable, the way it's currently used??
– user1660256
Feb 10 '17 at 12:06
Also, we decided we didn't want to put a sleep in a unit test method. So for now we're just going to test it during integration.
– user1660256
Feb 10 '17 at 12:06
"we decided we didn't want to put a sleep in a unit test method." wtith the change I suggestet the resulting method would be *to simple to fail" so that is would be no risk not to UnitTest is, but you could still thest the logic of the rinnable/CompletableFuture.
– Timothy Truckle
Feb 10 '17 at 12:11
|
show 1 more comment
I tried looking this up, but couldn't quite understand the examples I found. I have a class with a Spring AfterPropertiesSet()
method that calls 2 other methods to spin off asynch calls. I'm at a loss how as to to unit test them. The method startProcessingThread()
looks like this:
void startProcessingThread(executor) {
CompletableFuture.runAsync(() -> {
Path filePath = null;
do {
filePath = retrieveFromFileQueue();
submitFileForProcessing(filePath);
} while (keepRunning);
}, executor)
.handle((theVoid, exception) -> {
if (exception != null) {
LOG.error("Error submitting file for processing: " + exception);
}
return null;
});
}
I don't want to rewrite the CompletableFuture
in the test method (do I?). So I figured I need to call startProcessingThread()
, using Mocks (from Mockito) inside the methods that need them (retrieveFromFileQueue()
and submitFileForProcessing()
). But what about the CompletableFuture
itself? Should I mock that? I'm sorry, but I'm really confused...
java unit-testing
I tried looking this up, but couldn't quite understand the examples I found. I have a class with a Spring AfterPropertiesSet()
method that calls 2 other methods to spin off asynch calls. I'm at a loss how as to to unit test them. The method startProcessingThread()
looks like this:
void startProcessingThread(executor) {
CompletableFuture.runAsync(() -> {
Path filePath = null;
do {
filePath = retrieveFromFileQueue();
submitFileForProcessing(filePath);
} while (keepRunning);
}, executor)
.handle((theVoid, exception) -> {
if (exception != null) {
LOG.error("Error submitting file for processing: " + exception);
}
return null;
});
}
I don't want to rewrite the CompletableFuture
in the test method (do I?). So I figured I need to call startProcessingThread()
, using Mocks (from Mockito) inside the methods that need them (retrieveFromFileQueue()
and submitFileForProcessing()
). But what about the CompletableFuture
itself? Should I mock that? I'm sorry, but I'm really confused...
java unit-testing
java unit-testing
edited Feb 8 '17 at 14:01
user1660256
asked Feb 8 '17 at 13:54
user1660256user1660256
42741023
42741023
This code does not wait for theCompletableFutur
to finish nor it uses it's result. Why did you choose it in favour to an ordinaryRunnable
?
– Timothy Truckle
Feb 10 '17 at 8:27
You should create the lambda in a different method (or as an class of its own). Then you can mock it and check, that this method runs it (have your test wait a few ms after calling the method), also you can verify the lambdas behavior itself directly.
– Timothy Truckle
Feb 10 '17 at 8:29
Timothy, this code is not my design. I'm not really sure why a CompletableFuture was used. Does it not have any advantages over a Runnable, the way it's currently used??
– user1660256
Feb 10 '17 at 12:06
Also, we decided we didn't want to put a sleep in a unit test method. So for now we're just going to test it during integration.
– user1660256
Feb 10 '17 at 12:06
"we decided we didn't want to put a sleep in a unit test method." wtith the change I suggestet the resulting method would be *to simple to fail" so that is would be no risk not to UnitTest is, but you could still thest the logic of the rinnable/CompletableFuture.
– Timothy Truckle
Feb 10 '17 at 12:11
|
show 1 more comment
This code does not wait for theCompletableFutur
to finish nor it uses it's result. Why did you choose it in favour to an ordinaryRunnable
?
– Timothy Truckle
Feb 10 '17 at 8:27
You should create the lambda in a different method (or as an class of its own). Then you can mock it and check, that this method runs it (have your test wait a few ms after calling the method), also you can verify the lambdas behavior itself directly.
– Timothy Truckle
Feb 10 '17 at 8:29
Timothy, this code is not my design. I'm not really sure why a CompletableFuture was used. Does it not have any advantages over a Runnable, the way it's currently used??
– user1660256
Feb 10 '17 at 12:06
Also, we decided we didn't want to put a sleep in a unit test method. So for now we're just going to test it during integration.
– user1660256
Feb 10 '17 at 12:06
"we decided we didn't want to put a sleep in a unit test method." wtith the change I suggestet the resulting method would be *to simple to fail" so that is would be no risk not to UnitTest is, but you could still thest the logic of the rinnable/CompletableFuture.
– Timothy Truckle
Feb 10 '17 at 12:11
This code does not wait for the
CompletableFutur
to finish nor it uses it's result. Why did you choose it in favour to an ordinary Runnable
?– Timothy Truckle
Feb 10 '17 at 8:27
This code does not wait for the
CompletableFutur
to finish nor it uses it's result. Why did you choose it in favour to an ordinary Runnable
?– Timothy Truckle
Feb 10 '17 at 8:27
You should create the lambda in a different method (or as an class of its own). Then you can mock it and check, that this method runs it (have your test wait a few ms after calling the method), also you can verify the lambdas behavior itself directly.
– Timothy Truckle
Feb 10 '17 at 8:29
You should create the lambda in a different method (or as an class of its own). Then you can mock it and check, that this method runs it (have your test wait a few ms after calling the method), also you can verify the lambdas behavior itself directly.
– Timothy Truckle
Feb 10 '17 at 8:29
Timothy, this code is not my design. I'm not really sure why a CompletableFuture was used. Does it not have any advantages over a Runnable, the way it's currently used??
– user1660256
Feb 10 '17 at 12:06
Timothy, this code is not my design. I'm not really sure why a CompletableFuture was used. Does it not have any advantages over a Runnable, the way it's currently used??
– user1660256
Feb 10 '17 at 12:06
Also, we decided we didn't want to put a sleep in a unit test method. So for now we're just going to test it during integration.
– user1660256
Feb 10 '17 at 12:06
Also, we decided we didn't want to put a sleep in a unit test method. So for now we're just going to test it during integration.
– user1660256
Feb 10 '17 at 12:06
"we decided we didn't want to put a sleep in a unit test method." wtith the change I suggestet the resulting method would be *to simple to fail" so that is would be no risk not to UnitTest is, but you could still thest the logic of the rinnable/CompletableFuture.
– Timothy Truckle
Feb 10 '17 at 12:11
"we decided we didn't want to put a sleep in a unit test method." wtith the change I suggestet the resulting method would be *to simple to fail" so that is would be no risk not to UnitTest is, but you could still thest the logic of the rinnable/CompletableFuture.
– Timothy Truckle
Feb 10 '17 at 12:11
|
show 1 more comment
1 Answer
1
active
oldest
votes
You should avoid non deterministic logic in your test and so I would advise to avoid sleep. Instead you can use Mockito's "when" instead of "verify" and wait until the action was performed:
final xyz result = new{null};
final CountDownLatch latch = new CountDownLatch(1);
when(submitFileForProcessing(...).thenAnswer((Answer<Lwm2mCommand>) invocationOnMock ->
{
result[0] = invocationOnMock.getArgument(index); // if you need to check the values passed to your method call
latch.countDown();
}
// Call your method
assertTrue(latch.await(60L, TimeUnit.SECONDS));
// If needed check the parameters passed to the mocked method
One more tip: I wouldn't mock the actual class under test - instead I would mock one of the dependencies used.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42115038%2fhow-do-i-unit-test-a-method-that-contains-a-completablefuture%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You should avoid non deterministic logic in your test and so I would advise to avoid sleep. Instead you can use Mockito's "when" instead of "verify" and wait until the action was performed:
final xyz result = new{null};
final CountDownLatch latch = new CountDownLatch(1);
when(submitFileForProcessing(...).thenAnswer((Answer<Lwm2mCommand>) invocationOnMock ->
{
result[0] = invocationOnMock.getArgument(index); // if you need to check the values passed to your method call
latch.countDown();
}
// Call your method
assertTrue(latch.await(60L, TimeUnit.SECONDS));
// If needed check the parameters passed to the mocked method
One more tip: I wouldn't mock the actual class under test - instead I would mock one of the dependencies used.
add a comment |
You should avoid non deterministic logic in your test and so I would advise to avoid sleep. Instead you can use Mockito's "when" instead of "verify" and wait until the action was performed:
final xyz result = new{null};
final CountDownLatch latch = new CountDownLatch(1);
when(submitFileForProcessing(...).thenAnswer((Answer<Lwm2mCommand>) invocationOnMock ->
{
result[0] = invocationOnMock.getArgument(index); // if you need to check the values passed to your method call
latch.countDown();
}
// Call your method
assertTrue(latch.await(60L, TimeUnit.SECONDS));
// If needed check the parameters passed to the mocked method
One more tip: I wouldn't mock the actual class under test - instead I would mock one of the dependencies used.
add a comment |
You should avoid non deterministic logic in your test and so I would advise to avoid sleep. Instead you can use Mockito's "when" instead of "verify" and wait until the action was performed:
final xyz result = new{null};
final CountDownLatch latch = new CountDownLatch(1);
when(submitFileForProcessing(...).thenAnswer((Answer<Lwm2mCommand>) invocationOnMock ->
{
result[0] = invocationOnMock.getArgument(index); // if you need to check the values passed to your method call
latch.countDown();
}
// Call your method
assertTrue(latch.await(60L, TimeUnit.SECONDS));
// If needed check the parameters passed to the mocked method
One more tip: I wouldn't mock the actual class under test - instead I would mock one of the dependencies used.
You should avoid non deterministic logic in your test and so I would advise to avoid sleep. Instead you can use Mockito's "when" instead of "verify" and wait until the action was performed:
final xyz result = new{null};
final CountDownLatch latch = new CountDownLatch(1);
when(submitFileForProcessing(...).thenAnswer((Answer<Lwm2mCommand>) invocationOnMock ->
{
result[0] = invocationOnMock.getArgument(index); // if you need to check the values passed to your method call
latch.countDown();
}
// Call your method
assertTrue(latch.await(60L, TimeUnit.SECONDS));
// If needed check the parameters passed to the mocked method
One more tip: I wouldn't mock the actual class under test - instead I would mock one of the dependencies used.
answered Dec 31 '18 at 14:45
Dror HelperDror Helper
23.8k1368123
23.8k1368123
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42115038%2fhow-do-i-unit-test-a-method-that-contains-a-completablefuture%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This code does not wait for the
CompletableFutur
to finish nor it uses it's result. Why did you choose it in favour to an ordinaryRunnable
?– Timothy Truckle
Feb 10 '17 at 8:27
You should create the lambda in a different method (or as an class of its own). Then you can mock it and check, that this method runs it (have your test wait a few ms after calling the method), also you can verify the lambdas behavior itself directly.
– Timothy Truckle
Feb 10 '17 at 8:29
Timothy, this code is not my design. I'm not really sure why a CompletableFuture was used. Does it not have any advantages over a Runnable, the way it's currently used??
– user1660256
Feb 10 '17 at 12:06
Also, we decided we didn't want to put a sleep in a unit test method. So for now we're just going to test it during integration.
– user1660256
Feb 10 '17 at 12:06
"we decided we didn't want to put a sleep in a unit test method." wtith the change I suggestet the resulting method would be *to simple to fail" so that is would be no risk not to UnitTest is, but you could still thest the logic of the rinnable/CompletableFuture.
– Timothy Truckle
Feb 10 '17 at 12:11