I need to write a JUnit test case for a never ending main() method. This main() method after processing some files sleeps for a minute and then resumes its execution. This process goes on and on and on.
I used the below code to write JUnit for it:
#Test (timeout = 10000)
public void testMainMethod()
{
ClassName.main(null);
assertEquals(true, true);
}
And with no surprise, my test case failed with java.lang.Exception: test timed out after 10000 milliseconds message. Even when the main() method works as expected, this test case is going to be failed with the timeout exception. How could i override the behavior of this failing test case so that in case of timeout exception it should show the result as "Succeeded" for this test case.
Edit
The actual requirement is:
I need to search the files from a particular location and, if found any, then move them to different folder. This search should be done every 30 minutes. For this i have used below code:
public class FaxProcessor {
public static void main(String[] args) {
LOGGER.info("*** Starting Fax Server Processor ***");
int poll_time = 1800000;
LOGGER.info("Poll Time set to " + poll_time + " millisec");
FaxProcessor faxProcessor = new FaxProcessor();
while (true) {
try {
if(LOGGER.debugEnabled()){
LOGGER.debug("Starting new pass of fax processor");
}
faxProcessor.startProcessing();
} catch (Exception e) {
LOGGER.error("Processing Error", e);
} finally {
try {
// Wait for next loop
Thread.sleep(poll_time);
} catch (InterruptedException e) {
LOGGER.error("Thread Exception", e);
}
}
}
}
// startProcessing and other private methods here
}
The biggest problem is, I have only one public method {main() method} and all others are private, so i cant write JUnit test case for them. Also, main() method is not returning anything, it only moves files from one folder to another, and in case it fails in moving files in one pass, it tries to do the same in next pass. So using JUnit test case, i only want to check whether an unexpected exception is coming during whole process or not.
If i will not specify timeout in JUnit, the test case is never gonna complete then. As soon as the timeout occurs, i want to check, whether the test case is completed due to Timeout exception or some other exception has come from inside main() method that haulted JUnit test case.
In case it's Timeout exception, this implies, everything inside my program, went in the right direction till the timeout occured, so the test case should SUCCEED. In all other case it should show FAILED as JUnit status.
You have artificially constrained your testing environment, with this statement: "I have only one public method {main() method} and all others are private" -- who says? If this is a requirement imposed by your teacher, then you should seriously consider getting out of the class.
1) Proper testing means testing a) that candidate files are recognized, b) that candidate files are moved, and c) the operation occurs periodically.
2) Factor your main routine into the infinite-loop control part and the worker part. Even better, make the wait interval be a computed value.
3) Use protected methods instead of private methods. Since they are protected, you can now use a sub-class to get access to methods as you need, without violating necessary encapsulation.
You should think of separating long running unit tests. How to achieve that is for example shown here or here.
I don't understand what you want to do.
If you got Timeout Exception, that means the test case ran too long.
If you want to test the main method, and it contains an infinite loop, how can you determine that the method works as expected?
For your problem, use
#Test (timeout = 10000, expected=Exception.class)
Related
I have a method like the following one :
void enact(#NonNull final Request request) {
XInput input = this.xBuilder.buildInputPayload(request);
final Thread componentThread = new Thread(()->this.component.runJob(input));
componentThread.start();
return;
}
void testVTService_Success() {
when(xBuilder.buildInputPayload(any(Request.class))).thenReturn(inputPayloadWithAllArguments);
activity.enact(TestConstants.request);
verify(component, times(1)). runJob(any(XInput.class)); //Verification
}
Upon verification that the component.runJob() method is being executed it is throwing an error stating that Wanted but not invoked: component.runJob() Actually, there were zero interactions with this mock.
How do I fix this? And verify if the thread is starting & executing the runJob method?
Your test is running on one thread, and your code under test runs a new thread.
This means that your test verification runs before the runJob method because of multithreading.
At that point the test saying "Wanted but not invoked" is correct (the test code ran, checked if the production method had ran, it had not ... aand then in the background the production code ran (too late)).
Ideally you should separate the control of threading from the logic in your app. Wrap the Thread in a ThreadFactory, for real code you can pass an actual Thread, for test code you can pass an object that runs the code instantly (on the same thread).
Or (not recommended) you hack your test (this will help you understand):
void testVTService_Success() {
when(xBuilder.buildInputPayload(any(Request.class)))
.thenReturn(inputPayloadWithAllArguments);
activity.enact(TestConstants.request);
try { Thread.sleep(TimeUnit.SECONDS.toMillis(10)); } catch (Exception e) { assertTrue(false); }
verify(component, times(1)). runJob(any(XInput.class));
}
Now your test will always take 10 seconds, but hopefully the production code doesn't take 10 seconds to complete execution?
This is not ideal, like I said originally you would want to pull the Thread out of that Method, pass in some type of Factory to the class and pass a Fake object in the test. (Thus avoiding trying to test multithreaded code.)
I'm working on the system test of a IOT device that has various webservices.
We have 2 types, one with slow flash and the newer with faster flash memory. in the new flash the fw update can be done with aprox. 4 minutes while the slow ones take something around 12 minutes.
The problem comes in the junit test that tests the update and go back to the "previous" version. After sending the file and the update signal to the device, i use a Thread.sleep(6*60*1000) to wait for the device to expand the file, update and restart.
The junit test "skips" the test after 600s have passed, not failure, not error, just skips to the next test class..
It looks like it finished, but it just skipped the rest of the test WHILE it is inside the sleep
a small snippet of the test code althought it is mostly propietary:
public RequestCase(String path, WebServiceRequest req, WebServiceResponse resExp, String tcDesc, boolean validateResXSD) {
//super();
this.setPath(path);
this.setReq(req);
this.setResExp(resExp);
this.res = new WebServiceResponse();
this.setTcDesc(tcDesc);
this.setValidateResXSD(validateResXSD);
}
and the test snippet:
// now apply Software
String s06Req = null;
try {
s06Req = WebServiceRequestS06.makeCommandPsu(updFile.getRevision(), WebServiceRequestS06.SW_UPD);
} catch (WebServiceXMLException e) {
fail("Error creating S06 XML request. Error is: "+e.getMessage()+"\nAnd cause is :"+e.getCause());
}
RequestCase s06CommandPsu = new RequestCase(
null,
new WebServiceRequest("commandPsu", "POST", s06Req),
WebServiceResponse.RESULT_STATUS_CMD_SW_RECEIVED,
"Apply valid SW, and it is only received, but not apply now (imply Y03)",
true
);
executeCase(s06CommandPsu, WebServicesXSDValidator.S06_CommandPsu);
// Wait some time to wait charger apply new SW and reboot
try {
if (this.charger.getProductType() == Charger.ID_CT1_OLD_FLASH) {
Thread.sleep(6*60*1000);
} else {
Thread.sleep(2*60*1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
can someone help me a bit? Thanks in advance!
The test code snippet provided hre is not showing any assert/verify operation.
You have a test that sits there, waiting 600 seconds. Then it will end.
And the test will show up as passed (as it didn't cause a failure or error).
Thus:
If your tests should do something after 600 seconds, you have to code that.
Unrelated: you really should step back first. Unit tests should pass quickly, having it wait 600 seconds is not a good idea (assuming that we are talking real unit tests here, not an integration test)
Finally i found what was causing this, i will post it just in case someone stomps at the same problem.
it was caused due to the Parallelized class, more specifically in the ExecutorService awaitTermination() method where you can set a timeout..
I have a simple test case:
public class FileManagerTest {
String dirPath = “/myDir/”
#Before
public void setUp() {
mFileManager = MyFileManager.getInstance();
}
#Test
private void testPersistFiles() {
System.out.println(“testPersistFiles()…”);
//it deletes old files & persists new files to /myDir/ directory
boolean successful =mFileManager.persistFiles();
Assert.assertTrue(successful);
}
#Test
public void testGetFiles() {
System.out.println(“testGetFiles()…”);
mFileManager.persistFiles();
//I double checked, the persistFiles() works, the files are persisted.
List<File> files = mFileManager.getFilesAtPath(dirPath);
Assert.assertNotNull(files); //Failure here!!!!
}
#Test
public void testGetFilesMap() {
System.out.println(“testGetFilesMap()…”);
mFileManager.persistFiles();
Map<String, File> filesMap = mFileManager.getFilesMapAtPath(dirPath);
Assert.assertNotNull(files);
}
}
The persistFiles() function in FileManager delete all files under /myDir/ then persist files again.
As you see above, I have a System.out.println(…) in each test function. When I run it , I can see all the prints in the following order:
testGetFilesMap()…
testGetFiles()…
testPersistFiles()…
However, test is failed at testGetFiles(). Two things I don't understand:
I don’t understand, it is failed at testGetFiles() why I can still see the print testPersistFiles() which sounds like even it is failed, it doesn't stop running, but continues to run the next test testPersistFiles()? What is happening behind the scene in JUnit test case??
Another thing I don’t understand is why testGetFiles() is failed? I can see log that the persistFiles() has persisted files. Why it got null after that?
I don’t understand, it is failed at testGetFiles() why I can still see the print testPersistFiles() which sounds like even it is failed, i
That is how unit testing works. Each test should be isolated and working using only its set of data. Unit test frameworks run every test so you can see which parts of the system work and which do not, they do not stop on the first failure.
mFileManager.getFilesAtPath(dirPath);
You are not searching the files in the right place
String dirPath = “/myDir/”
Are you sure that this path is ok? with a slash before the directory name?
For each of your tests, JUnit creates a separate instance of that class and runs it. Since you seem to have 3 tests, JUnit will create 3 instances of your class, execute #Before on each of them to initialize state, and then run them.
The order in which they are run is typically the order in which the tests are written but this is not guaranteed.
Now about the print statement - you see that it's the first statement in your test so it will be executed. Then mFileManager.persistFiles(); is executed. For some reason it returns a false and hence the test fails.
As to why it returns false, you can run a local debugger, put a break point at the beginning of that method, single-step and see.
i am looping a method with a Thread which reads from a website(dynamically)
all the methods work perfectly, but my problem is that sometimes (3 out of 10 times) that i start the program it throws IO exception at me although i haven't changed my input data from the last known good execution , the exception is coming from the method below:
public String readThisUrlContent() throws ExceptionHandler
{
try {
#SuppressWarnings("static-access")
Document doc = Jsoup.connect(url).timeout(1000).get();
return doc.body().text();
} catch (IOException e) {
throw new ExceptionHandler("IO Exception for reading the site in method setUrlContent in Url class");
}
}
my best guess is that since i'm reading more than one Url with looping this method but the timeout is not sometimes at the best range (considering the internet speed etc. it sometimes doesn't work) but its just my theory and it can be dead wrong but even if its correct i have no idea how to handle it
The problem exactly was the time to live of the opened port. since i had other functions working at the same time program simply needed more connected time so i expanded timeout to (5000) and also reduced the timer of another Time.Schedule method in another method, and so it worked
I'm relatively new with hibernate so please be gentle. I'm having an issue with a long running method (~2 min long) and changing the value of a status field on an object stored in the DB. The pseudo-code below should help explain my issue.
public foo(thing) {
if (thing.getStatus() == "ready") {
thing.setStatus("finished");
doSomethingAndTakeALongTime();
} else {
// Thing already has a status of finished. Send the user back a message.
}
}
The pseudo-code shouldn't take much explanation. I want doSomethingAndTakeALongTime() to run, but only if it has a status of "ready". My issue arises whenever it takes 2 minutes for doSomethingAndTakeALongTime() to finish and the change to thing's status field doesn't get persisted to the database until it leaves foo(). So another user can put in a request during those 2 minutes and the if statement will evaluate to true.
I've already tried updating the field and flushing the session manually, but it didn't seem to work. I'm not sure what to do from here and would appreciate any help.
PS: My hibernate session is managed by spring.
Basically you need to let it run in a separate Thread to make the method to return immediately. Else it will indeed block until the long running task is finished. You can pass the entity itself to the thread, so that it can update the status itself. Here's a basic kickoff example using a simple Thread.
public class Task extends Thread {
private Entity entity;
public Task(Entity entity) {
this.entity = entity;
}
public void run() {
entity.setStatus(Status.RUNNING);
// ...
// Long running task here.
// ...
entity.setStatus(Status.FINISHED);
}
}
and
public synchronized void foo(Entity entity) {
if (entity.getStatus() == Status.READY) {
new Task(entity).start();
} else {
// ...
}
}
With the Status in an enum you can even use a switch statement instead of an if/else.
switch (entity.getStatus()) {
case READY:
new Task(entity).start();
break;
case RUNNING:
// It is still running .. Have patience!
break;
case FINISHED:
// It is finished!
break;
}
For a more robust control of running threads, you may want to consider ExecutorService instead. Therewith you can control the maximum number of threads and specify a timeout.
What the method doSomethingAndTakeALongTime() is doing? is it for DB operation or just executing some business logic?
If its not doing any DB operation, and you got your status fine then you can persist the object before calling that method.
And if its doing some DB operation, then you need to wait for it. So, even if you put in thread you need to wait for that thread to complete (using thread.join() we can do that)
the thing is, before you persist you must have completed all operation based on you ORM object right? so try to optimized the logic for the method to get it executed before you persist.
thanks.