Let's say I have method like this:
public int toTest() {
try { Thread.sleep(60 * 1_000); }
catch (InterruptedException ignored) {}
return 8;
}
And I would like to test it e.g. check if returned value is correct, like this:
#Test
public void test() {
int actual = toTest();
assertThat(actual).isEqualTo(8);
}
Is there any way to "simulate" time lapse so during test execution I will not be force to wait for whole minute?
Edit:
Probably I described my question too concrete. I didn't want to focus on this exact one minute but on way to bypass it. There could be even 100 days but my question is if there is method to simulate this time lapse.
Like in project reactor methods with are using virtual time https://projectreactor.io/docs/test/snapshot/api/reactor/test/StepVerifier.html#withVirtualTime-java.util.function.Supplier-
You can achieve that using Powermock.
// This will mock sleep method
PowerMock.mockStatic(Thread.class, methods(Thread.class, "sleep"));
PowerMockito.doThrow(new InterruptedException()).when(Thread.class);
Thread.sleep(Mockito.anyLong());
At the start of class, you will need to add this
#PrepareForTest(YourClassToWhich_ToTest_MethodBelong.class)
JUnit test the method as is (unless you add mocking..) if you want you can test internal method as toTestInternal:
public int toTest() {
try { Thread.sleep(60 * 1_000); }
catch (InterruptedException ignored) {}
return toTestInternal();
}
public int toTestInternal() {
return 8;
}
and test the method you want (toTestInternal):
#Test
public void test() {
int actual = toTestInternal();
assertThat(actual).isEqualTo(8);
}
I would suggest to make the interval a dynamic parameter. It will save your time:
public int toTest(int interval) {
try {
Thread.sleep(interval);
}catch (InterruptedException ignored) {}
return 8;
}
and the test class to be like:
#Test
public void test() {
int actual = toTest(60);
assertThat(actual).isEqualTo(8);
}
Related
I have a regular, non-static sendMail method which may occasionally fail. I need to catch any errors and retry the method N number of times. I'm not sure I'm doing the right thing, and there's also a compilation error:
public void sendMail(List<String> params) {
try {
//...
static int retrycount = 0; // static not allowed here (but need to keep static var for recursion)
int maxretries = 3;
}
catch (Exception e) {
log.info(e);
// Recursion to retry
sendMail(params);
retrycount++;
}
}
First of all, is recursion from a try/catch block correct? Also, is there a better way to do this?
I can't make the sendMail method static, there are too many references to it in the existing code.
Your retry will never work in the first place because inside every try block you are setting retrycount to 0.
You'd probably be better off throwing the exception instead of catching it. Then using some kind of a while loop till it completes, maybe with a configurable delay between retries. Or if you're using Spring there is the Retryable annotation.
void someMethod(){
int attempts = 0;
while(attemps <= 3){
try {
sendMail(...);
break;
} catch (Exception e){
attempts++;
// Log failed to send mail or something meaningful, maybe add a delay here?
}
}
}
This solution is much cleaner than using recursion as if you wanted to retry many times, eventually you'd get a stack overflow error. It also keeps the responsbility of the sendMail function simple, and avoids adding complicated retry logic to an otherwise simple method.
Also, if you end up having to make other methods retryable in the same fashion then it would be much easier to abstract away the retry logic into some kind of executor service that handles it all.
What if you just wrapped the code in a retry loop:
public void sendMail(List<String> params) {
for (int attempt = 0; attempt < 3; attempt++)
try {
//...
if (<some success condition>)
return;
}
catch (Exception e) {
log.info(e);
}
}
The standard recursive solution would be to add retryCount as a paremeter.
public void sendMail(List<String> params) {
sendMail(params, 0);
}
private void sendMail(List<String> params, int retryCount) {
try {
//...
int maxRetries = 3;
} catch (Exception e) {
log.info(e);
// Recursion to retry
sendMail(params, retryCount+1);
}
}
A loop would be the more idiomatic way of writing this.
public void sendMail(List<String> params) {
int maxTries = 4;
for (int tryCount=0; tryCount<maxTries; ++tryCount) {
try {
//...
break;
} catch (Exception e) {
log.info(e);
// continue to retry
}
}
}
In the spirit of the original question, the retryCount can be kept as a field within an introduced object. It's easiest (if slightly obscure) to do this with an anonymous inner class.
public void sendMail(List<String> params) {
int maxTries = 4;
new Object() {
int tryCount = 0;
public void sendMail() {
try {
//...
} catch (Exception e) {
log.info(e);
// Recursion to retry
if (tryCount < maxTries) {
++tryCount;
sendMail();
}
}
}
}.sendMail();
}
I need to provide code that using ExecutorService, Callable and Future will be doing some calculations and printing the partial results until defined condition is reached. First thing that comes to my mind is using while loop. Unfortunately as I understand ExecutorService.get() waits until the task is done, so I cannot do something like (pseudo code):
public Object call() throws Exception {
try {
while(!condition) {
//perform calc
return partialCalculationResult;
}
}
catch(InterruptedException e){
}
}
Could anyone guide me what's the proper direction I should go for?
This here:
while(!condition) {
//perform calc
return partialCalculationResult;
}
indicates a "hole" in your logic. This should probably go like this instead:
while(!condition) {
// perform computation
push intermediate results somewhere
}
return finalResult;
In other words: you are talking about two different elements here. For those "progress" updates you will need some kind of shared data structure; for example a Queue.
You see, in difference to other languages, there is no built-in "generator" concept that would allow you to yield values from a loop; like you can do in python or scala for example.
The dirty option is putting a System.out.println within the while loop.
The cleaner option would be a publish/subscriber pattern, like:
interface Subscriber {
void onPartialResult(double partialResult);
}
class SystemOutSubscriber implements Subscriber{
#Override
void onPartialResult(double partialResult) {
System.out.println(partialResult);
}
}
class YourCalculatorClass {
List<Subscriber> subscribers = ...
public Object call() throws Exception {
while(!condition) {
//perform calc
for(Subscriber s : subscribers) {
s.onPartialResult(partialCalculationResult);
}
}
}
}
You can use Thread.interrupt to stop the thread inside while loop and add remaining result in list
while(!condition){ list.add(addResultHere)
Thread.interrupt(); }
Below is a small example of using an ExecutorService
to push callable tasks. I push them inside a while loop now for the ease of the example, but they can come from anywhere. The callable itself uses the most silly easy example of course where it takes in a number. If the number is below 5, all is good, and we return a text. If not, we return nothing. When the future is evaluated and the result is empty, we shut down the ExecutorService and call it a day. So, this is an example of using an ExecutorService, Callable, and Future to do something at least similar to what I could discern from your explanation.
public ExecutorServiceTest() {
ExecutorService service = Executors.newCachedThreadPool();
int num = 0;
while (true) {
Future<Optional<String>> future = service.submit(new MyCallable(num++));
try {
Optional<String> result = future.get();
if (!result.isPresent()) {
service.shutdown();
break;
}
System.out.println(result.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
service.shutdown();
}
}
}
private static class MyCallable implements Callable<Optional<String>> {
private final int num;
MyCallable(int num) {
this.num = num;
}
#Override
public Optional<String> call() throws Exception {
if (num < 5)
return Optional.of("My number is " + num);
return Optional.empty();
}
}
public static void main(String[] args) {
new ExecutorServiceTest();
}
In Intelij and Eclipse IDEs (and probably some others too) it's possible to run all test classes from a package (or even all test classes in a project) without the need to put each of them explicitly in a test suite class (this is something I want to avoid). Just right click -> run all tests and voilĂ !
I've got one problem with that approach to testing though. I want to do some cleaning up after all the tests are done, but no matter what I do, nothing seems to work.
At first, I tried using RunListener and its testRunFinished() method, but it is called after every atomic test is done, so not what I want when running many of them.
Then I thought about finalizers and runFinalizersOnExit(true), unfortunatelly, it is deprecated and worked only on one of computers that tests are executed on.
Last thing I tried was to create a "listener" thread, that - given tests execution start and end time differences - would clean up, for instance, after five seconds of test completion. I used code below to test that solution:
import org.junit.Test;
public class Main {
static {
System.out.println("In a static block!");
new Thread(new Runnable() {
public void run() {
System.out.println("Starting static thread!");
try {
while (true) {
Thread.sleep(1000);
System.out.println("Static thread working...");
}
} catch (InterruptedException e) {
System.err.println("Static thread interrupted!");
e.printStackTrace();
} catch (Exception e) {
System.err.println("Static thread catches exception!");
e.printStackTrace();
} finally {
System.err.println("Static thread in finally method.");
Thread.currentThread().interrupt();
}
}
}).start();
System.out.println("Exiting static block!");
}
#Test
public void test() throws Exception {
System.out.println("Running test!");
Thread.sleep(3000);
System.out.println("Stopping test!");
}
}
With no luck. The thread is killed after the test is done. And even the finally block is never executed...
In a static block!
Exiting static block!
Running test!
Starting static thread!
Static thread working...
Static thread working...
Stopping test!
Static thread working...
Desired behavior would be:
right click
run all tests
TestA is running...
TestA done
TestB is running...
TestB done
... more test classes...
cleanup
Not sure if I fully have your question right, but I think you want before, beforeClass, after and afterClass methods. i.e.
#BeforeClass
public void beforeClass() {
// Do stuff before test class is run
}
#Before
public void before() {
// Do stuff before each test is run
}
#After
public void after() {
// DO stuff after each test is run
}
#AfterClass
public void afterClass() {
// DO stuff after test class is run
}
You can do things on a more global level with some hacking or other frameworks. Spring's test suites for example. But I would try to keep such things within the scope of a single test class.
I've found a solution to my problem. My colleague suggested "hey, can't you just count the test classes?" - and that's what I did.
A little bit of reflection magic is used here, so the code might not be portable:
public abstract class CleaningTestRunner extends BlockJUnit4ClassRunner {
protected abstract void cleanupAfterAllTestRuns();
private static long TEST_CLASSES_AMOUNT;
private static long TEST_RUNS_FINISHED = 0;
private static boolean CLASSES_COUNTED = false;
static {
while (!CLASSES_COUNTED) {
try {
Field f = ClassLoader.class.getDeclaredField("classes");
f.setAccessible(true);
Vector<Class> classes = (Vector<Class>) f.get(CleaningTestRunner.class.getClassLoader());
TEST_CLASSES_AMOUNT = 0;
for (Class<?> klass : classes) {
if (klass.isAnnotationPresent(RunWith.class)) {
if (CleaningTestRunner.class.isAssignableFrom(klass.getAnnotation(RunWith.class).value())) {
for (Method method : klass.getMethods()) {
if (method.isAnnotationPresent(Test.class)) {
++TEST_CLASSES_AMOUNT;
break;
}
}
}
}
}
CLASSES_COUNTED = true;
} catch (Exception ignored) {
}
}
}
public CleaningTestRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
public void run(RunNotifier notifier) {
notifier.addListener(new TestCleanupListener());
super.run(notifier);
}
private class TestCleanupListener extends RunListener {
#Override
public void testRunFinished(Result result) throws Exception {
++TEST_RUNS_FINISHED;
if (TEST_RUNS_FINISHED == TEST_CLASSES_AMOUNT) {
cleanupAfterAllTestRuns();
}
}
}
}
I have a Test class with a method called public void httpcall(), I need to get the execution time of this method. In order to do this, I have used System.nanoTime() before and after calling it. I get the execution time from that duration.
code snippet:
public class Test{
public void httpcall(){
try {
HttpResponse rs = HttpClientUtil.get("http://192.169.1.2:9090/plugins/restapi/v1/users/9223370580466120397/roster",RestOpenfire.ACCEPT, "8V9BUNA0f1gNQI3S");
} catch (Exception e) {
System.out.println("Error : "+e);
}
}
public static void main(String[] args) {
Test test=new Test();
long startTime = System.nanoTime();
test.httpcall();
long endTime = System.nanoTime();
long duration = (endTime-startTime);
System.out.println("Execution Time : "+duration);
}
}
I want to make an annotation like #Time that gives an execution time of the method, something like ..
#Time
public void httpcall(){
try {
HttpResponse rs = HttpClientUtil.get("http://192.169.1.2:9090/plugins/restapi/v1/users/9223370580466120397/roster",
RestOpenfire.ACCEPT, "8V9BUNA0f1gNQI3S");
} catch (Exception e) {
System.out.println("Error : " + e);
}
}
How could I do this?
You can try to use aspectj which can either change your source code as part of your build, change your .class files in a process called weaving or change it on runtime.
https://mathewjhall.wordpress.com/2011/03/31/tracing-java-method-execution-with-aspectj/
Thought, it can be an overkill.
Unless you have a huge system that will be hard to refactor, I recommend using template methods. That is,
abstract class Measurable
{
protected void abstract doWork();
public void execute(){
stopWatch = StopWatch.start();
doWork();
stopWatch.stop();
System.out.println(stopWatch.getTime());
}
}
class MyHttpClient extends Measurable
{
doWork(){
HttpResponse rs = HttpClientUtil.get("http://192.169.1.2:9090/plugins/restapi/v1/users/9223370580466120397/roster",RestOpenfire.ACCEPT, "8V9BUNA0f1gNQI3S");
}
}
public static void main(String[] args) {
MyHttpClient test=new MyHttpClient();
test.execute();
}
And all uses of MyHttpClient will call the execute() method.
Also note that I used StopWatch class, since it is more elegant and standard than using System.currentTimeMillis. https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/StopWatch.html
Based on guava-libraries example, I am using ListenableFuture.
I am using:
java 1.6
JDeveloper 11.1.1.6.0
guava-13.0.1.jar
junit-4.5.jar
easymock-3.1.jar
powermock-easymock-1.4.12-full.jar
I am trying to ensure that method under test is called in async mode.
My Manager.java code is:
...
public synchronized void refreshAsync(final String id) {
m_Log.entry(id);
ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
ListenableFuture<Details> getDetailsTask =
service.submit(new Callable<Details>() {
#Override
public Details call() {
System.out.println(Thread.currentThread().toString());
return MyCacheManager.getDetails(id);
}
});
Futures.addCallback(getDetailsTask ,
new FutureCallback<Details>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Details details) {
System.out.println("Success");
//TODO: publish event
}
public void onFailure(Throwable thrown) {
System.out.println("Failed");
//TODO: log
}
});
service.shutdown();
m_Log.exit("done async");
}
...
My test is:
#RunWith(PowerMockRunner.class)
#PrepareForTest( { Manager.class, MyCacheManager.class, TWResourceManager.class, Logger.class })
public class DetailsTests {
{
...
#Test (timeout = 4000)
public void refreshAsync_RequestedInAsyncMode_NoWaitForComplete() throws Exception {
// Creating nice mock - because we are not caring about methods call order
mockStatic(MyCacheManager.class);
// Setup
final int operationTimeMilis = 5000;
expect(MyCacheManager.getDetails(anyObject(String.class))).andStubAnswer(new IAnswer<Details>() {
public Details answer() {
try {
System.out.println("start waiting 5 sec");
System.out.println(Thread.currentThread().toString());
Thread.sleep(operationTimeMilis);
System.out.println("finished waiting 5 sec");
} catch (InterruptedException e) {
e.printStackTrace();
}
return Details.getEmpty();
}
});
replay(MyCacheManager.class);
replayAll();
ISchemaActionsContract controller = new TWManager();
controller.refreshSchemaDetailsAsync("schema_id");
// We need not to verify mocks, since all we are testing is timeout
// verifyAll();
}
}
When I am running / debugging the test - it is always failed on timeout. It seems that mocked method "MyCacheManager.getDetails" is called in "sync" mode.
But when I am calling same function from regular code / debug - it is running in async mode (I put Thread.sleep(10000) into MyCacheManager.getDetails method, and Manager.refreshAsync method is exited without waiting / be blocked.
Also, If I am changing the method to use regular FutureTask, test pass as expected.
...
Object res = null;
FutureTask task = new FutureTask(new Runnable() {
#Override
public void run() {
MyCacheManager.getDetails(id);
}
}, res);
m_Log.debug("async mode - send request and do not wait for answer.");
Executors.newCachedThreadPool().submit(task);
Any idea will be more then welcome! :)
Thanks!