IllegalArgumentException: Invalid conditional statement inside expectation block - java

I have a problem with an Expectations block I have written in my test case:
new Expectations() {
{
mFindHandlerMock.findAll((Model) any, (Set<Id>) any, false);
if (!pWithRealData) {
result = Collections.emptySet();
} else {
result = pAllData;
}
times = 1;
Deencapsulation.invoke(mDb, "readSqlQuery", withAny(String.class));
result = "select * from realdata";
times = 1;
}
};
the test case crashes with:
java.lang.IllegalArgumentException: Invalid conditional statement inside expectation block
exactly here:
if (!pWithRealData) {
it's just a simple boolean that is false in this case.
I have absolutly no clue why the exception happens.
I already searched with google but found nothing helpful.
Could you help me?

From the JMockit release notes for version 1.14:
Enhancement: Conditionals and loops will now trigger an exception when found inside an expectation recording block, to prevent API misuse and to encourage simpler tests. See issue #97.
The GitHub issues related to this:
https://github.com/jmockit/jmockit1/issues/97
https://github.com/jmockit/jmockit1/issues/123
In the one issue they state that:
Yes, and this is as intended, to avoid tests getting too complicated when recording expectations. A full test was not shown, but it looks to me that recording the specific expectations directly would be better in this case.
In the JMockit source you can see which other types of conditionals and loops will throw that exception.
In short, from JMockit 1.14 onwards you are not allowed to have conditionals (such as if statements) and loops in the Expectation block.

Related

Esper: Creating new Esper statements, and skipping those that already exist

The project I'm working on uses Esper to create monitoring rules. These rules are either active or inactive, based on a boolean in the SQL row. I would like to set up a check to see if there are any new active rules, create a statement from the, and add them to a hashmap. This will periodically run using Spring scheduler. The code so far looks like this:
private void refreshStatement(Rule rule) throws Expression {
List<String> allRules = dao.getAllRules();
for (String rule : allRules) {
EPStatement statement = epService.getEPAdministrator().createEPL(rule);
statement.addListener(new RuleListener(rule));
ruleMap.put(rule.getId(), statement);
}
}
On the initial run, this works fine. The statements are generated and added to the hashmap ruleMap. Upon the method running a second time due to the scheduler, though, it fails due to the first rule it sees already existing. For example:
ERROR [2018-08-14 12:00:00,000] org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler: Unexpected error occurred in scheduled task.
! com.espertech.esper.epl.expression.core.ExprValidationException: Context by name 'Test_Case' already exists
Is there any good way to check to see if an Esper statement already exists, and to skip the rule if it does? So far, I've tried catching the exception and simply returning a log stating that the EPL statement already exists, that way only new statements would be created:
private Exception e;
private void refreshStatement(Rule rule) throws Exception {
List<String> allRules = dao.getAllRules;
for (String rule : allRules) {
if (e instanceof ExprValidationException) {
log.info("The EPL statement already exists")
}
else {
EPStatement statement = epService.getEPAdministrator().createEPL(rule);
statement.addListener(new RuleListener(rule));
ruleMap.put(rule.getId(), statement);
}
}
}
However, I still got the same exception.
Edit: I just realized that I wrote the for loop wrong. The program will fail on when creating statement, and since that is in the else portion of the loop, it thus never checks for the exception.
You can get the currently-existing statements from EPAdministrator.getStatementNames() and EPAdministrator.getStatement(String name).
Comparing whether a statement already exists is up to your application but EPStatement.getText() returns you the EPL.

How to override the behavior of a failed JUnit test case

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)

Anyone can tell me what's wrong with this pseudo code?

I am not familiar with JUnit so not sure if that's the problem of assertTrue(b_exception);, because if I put an System.out.println("something"); there, it would print out "something"... Thanks!!
Please note that it is pseudo code, focus on the logic.
b_exception = false;
try{
somethingThrowError();
}catch(Error e){
b_exception = true;
}
assertTrue(b_exception);
I don't know what the problem is with your code because you haven't stated how it fails to fulfill your expectations, but the correct idiom for testing that an exception is thrown is to use JUnit 4's annotations:
#Test(expected=SpecificError.class)
public void testError(){
somethingThrowError();
}
I can only guess that you are looking for this:
try{
somethingThrowError();
fail("Exception expected");
}catch(AsSpecificAsPossibleException e){
//should happen, OK
//optionally assert exception message, etc.
}
Also note that catching an Error is a bad idea, use as specific exception as you can.
UPDATE: #Michael Borgwardt's answer is actually even better, but only if there is nothing except a single line in your test (nothing else that can throw). Also #Test(expected does not allow you to perform extra exception message assertions (but should you?)
Not sure what you think is wrong with that code.
The assertTrue will always be executed, as will the System.out.println.
It - the assertTrue - will signal an error if the argument is not true, or "pass the test" if the argument is true.
Maybe you should use System.out.println("b_exception = " + b_exception); to see what is happening.

Stackoverflow calling metaClass method on Map

This piece of code is causing a stackOverflow exception:
ISerializer serializer = buildSerializer(TestDataProvider.getAuthor());
ASObject result = (ASObject) serializer.serialize();
assert result.isNotLazyProxy
The StackOverflow is being thrown on this line: assert result.isNotLazyProxy. Note, the isNotLazyProxy method never actually gets called.
isNotLazyProxy is a extension method (what are these called in groovy?) defined as follows:
/**
* Asserts that this ASObject is not a lazy loaded proxy,
* ie - that all of it's properties' values have been included
*/
ASObject.metaClass.isNotLazyProxy = { ->
assert delegate[HibernateProxyConstants.PROXYINITIALIZED] == true
return true;
}
However, setting a breakpoint on the first line of that closure shows that it never gets called.
Instead, there's a StackOverflow thrown:
java.lang.StackOverflowError
at java.lang.System.arraycopy(Native Method)
at java.lang.String.getChars(String.java:855)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:391)
at java.lang.StringBuffer.append(StringBuffer.java:224)
at java.lang.StringBuffer.<init>(StringBuffer.java:104)
at org.codehaus.groovy.runtime.InvokerHelper.formatMap(InvokerHelper.java:557)
at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:530)
at org.codehaus.groovy.runtime.InvokerHelper.formatList(InvokerHelper.java:602)
at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:527)
at org.codehaus.groovy.runtime.InvokerHelper.formatMap(InvokerHelper.java:575)
snip
I'm not sure if it's relevant, but ASObject is a subclass of a Map, and it's contents may have properties that refer to other keys within itself.
I would've have thought it was relevant, except the StackOverflow appears to indicate that groovy is traversing the members of the map.
What's going on? Why is this stackoverflow occurring?
assert result.isNotLazyProxy is probably not doing what you want to do.
In groovy map.somehing is translated to map.get(something). See http://groovy.codehaus.org/JN1035-Maps :
assert map2.class == null
//field syntax always refers to value of key, even if it doesn't exist
//use getClass() instead of class for maps...
assert map2.getClass() == LinkedHashMap //the kind of Map being used
So use assert result.isNotLazyProxy().
Of course result.isNotLazyProxy should return null in your case, and the assert result.isNotLazyProxy assertion should fail. When this assertion fails groovy will display an assertion error, and the map. In your case formatting the map fails for some reason.
Reason it fails:
It is a known bug, see example. As I see, it has nothing to do with ASObject, as it uses no lists.
At first glance, it looks like something else is causing the endless recursion...
Does ASObject have any other metaClass methods? Especially those overriding the getAt( key ) method of Map
I came up with this quick test script, and it seems to work fine as I'd expect (and I think it does the same as what you say you're doing)
class ASObject {
#Delegate Map map = [ 'PROXYINITIALIZED' : true ]
}
ASObject.metaClass.isNotLazyProxy = { ->
assert delegate[ 'PROXYINITIALIZED' ] == true
return true
}
assert new ASObject().isNotLazyProxy()

Assigning a value when an exception occurs (Java)

Here is some sample code to illustrate our issue:
A a = null;
try {
a = new A();
a = doSomethingThatWillThrowAnException();
} finally {
System.out.println("A = " + a);
}
The question is what is the value of 'a' as printed in the finally block...
I am not sure and I think I stumbled across something that might not be completely described. I observed on my laptop (jdk1.6.0.16 on x86) that 'a' is equal to A(). However, with a JDK 1.4 on Solaris I think that that the value is null (like if the assignment was performed even though the exception is thrown). This is obviously linked to a bug and we will deploy a version without the assignment just to make sure but we would like to know if one of you also noticed this or have some kind of explanation to propose.
What we will do, also, is to make a sample program to demonstrate this on the problematic JDK... and we will post the results.
The assignment should definitely not happen when an exception occurs - this would be a very serious bug in the JVM. But I'd first suspect that the exception actually occurs somewhere else (such in the constructor A()).
I would assume a == new A() unless it is optimized away. Isn't the code a bit silly looks like:
a=1;
a=2;
Maybe rewrite to the intend of your code:
A a = null;
try {
a = doSomethingThatWillThrowAnException();
} catch( ... ) {
a = new A();
}
Just did the test on Solaris with Sun JDK_1.4.2_05 on Solaris with the following program
public class Test {
public static void main(String[] args) throws Exception {
String test = null;
try {
test = "step1";
test = getString();
} finally {
System.out.println(test);
}
}
public static String getString() {
throw new RuntimeException();
}
}
I get the "step 1" in the console alright.
As other user have suggested, I think that the most likely is that the exception is thrown in the A() constructor. ( I hope that's the case, otherwise that would require some quite nasty defensive code )
If the optimizer can make sure that new A() has no side effects, it will optimize the first assignment away. To isolate this case, disable the JIT and run the code again. If a != null afterwards, you're seeing an optimizer glitch.
The obvious fix is to more the new A() before the try block:
A a = new A();
try {
a = doSomethingThatWillThrowAnException();
} finally {
System.out.println("A = " + a);
}
You could try compiling the code then looking at the bytecode to see what is going on. I use
the bytecode outliner eclipse plugin from http://andrei.gmxhome.de/eclipse/
I ran the code on Solaris 10 with the JDK 1.4.2 too and it had the correct behaviour. The problem was that the code in production was not the one I was looking at... (previous version)
It was interesting reading your answers though since it made it clear that optimizer glitches can happen and it is always a good idea to second guess what is going on under the hood.
Mental note for next time: "First, check the obvious: If you are having a strange behaviour, the code you are seing might not be what has been executed."
Thanks again,
Cedric

Categories