Search code examples
javajunitclasscastexceptioneclemma

java.lang.ClassCastException: Z cannot be cast to java.lang.String


I'm getting an error: java.lang.ClassCastException: Z cannot be cast to java.lang.String while trying to run coverage (EclEmma) on a Junit test. If I run the test regularly (without coverage) then it passes.

This is the code (all the fields in the class are Strings):

@Override
public Map<String, String> getErrors() throws IllegalAccessException, IllegalArgumentException {

    Map<String, String> errors = new HashMap<String, String>();

    for (Field field : this.getClass().getDeclaredFields()) {
        field.setAccessible(true);
        String value = (String) field.get(this);

        if (value.equals("N")) {
            if (!errors.containsKey(field.getName())) {
                errors.put(field.getName(), value);
            }
        }
    }
    return errors;
}

Solution

  • The problem is that to produce the code coverage EclEmma adds a field private static final transient boolean[] $jacocoData to your class.

    Since this field is only present during code coverage runs, the normal unit test passes, but the code coverage run fails: your original code is not expecting this non-String field.

    The best solution is to check if the field you are seeing is really a String field and otherwise skipping the test of the field value:

    for (Field field : this.getClass().getDeclaredFields()) {
        field.setAccessible(true);
        if (field.getType() != String.class) {
            continue;
        }
        String value = (String) field.get(this);
    
        if (value.equals("N")) {
            if (!errors.containsKey(field.getName())) {
                errors.put(field.getName(), value);
            }
        }
    }