Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot test class that has field of type java.util.List (interface) #51

Closed
GoogleCodeExporter opened this issue Mar 29, 2015 · 7 comments

Comments

@GoogleCodeExporter
Copy link

I have some class that has a field of type java.util.List (thus, an interface). 
When I run equalsverifier, I get the following exception:

java.lang.AssertionError: java.lang.AbstractMethodError: 
$java.util.List$$EnhancerByCGLIB$$b89655a4.iterator()Ljava/util/Iterator;
For more information, go to: 
http://code.google.com/p/equalsverifier/wiki/ErrorMessages
    at nl.jqno.equalsverifier.util.Assert.fail(Assert.java:96)
    at nl.jqno.equalsverifier.EqualsVerifier.handleError(EqualsVerifier.java:330)
    at nl.jqno.equalsverifier.EqualsVerifier.verify(EqualsVerifier.java:316)
    at ... 8-<

If I replace java.util.List with java.util.ArrayList (thus, a concrete 
implementation of interface List), it works.

Original issue reported on code.google.com by [email protected] on 25 Nov 2011 at 2:21

@GoogleCodeExporter
Copy link
Author

Hi,

EqualsVerifier is able to handle interface fields like you describe, including 
java.util.List. There are unit tests for precisely this use case.

Of course that doesn't mean something else isn't going on. Unfortunately, the 
stack trace doesn't give me enough information to see what's going on. Can you 
please post some code that triggers this error?

Regards,
Jan

Original comment by [email protected] on 26 Nov 2011 at 11:24

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

I investigated this issue and the class under test, respectively, further; it 
seems that the class' custom toString() implementation causes the issue:

    @Override
    public String toString() {
        final int maxLen = 10;
        return String.format("SomeClass [states=%s]", states != null ? toString(states, maxLen) : null);
    }

    private static String toString(Collection<?> collection, int maxLen) {
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        int i = 0;
        for (Iterator<?> iterator = collection.iterator(); iterator.hasNext() && i < maxLen; i++) {
            if (i > 0) {
                builder.append(", ");
            }
            builder.append(iterator.next());
        }
        builder.append("]");
        return builder.toString();
    }

I attached the whole class. Perhaps you could include it in equalsverifier's 
test suite as regression test?

Original comment by [email protected] on 28 Nov 2011 at 11:05

  • Added labels: ****
  • Removed labels: ****

Attachments:

@GoogleCodeExporter
Copy link
Author

I can reproduce the error.

EqualsVerifier instantiates a dynamically generated instance of java.util.List. 
Usually, this is fine, because it can fall back to Object's equals, hashCode 
and toString methods, and other methods of the List interface are usually not 
called by EqualsVerifier or by the equals and hashCode methods of the class 
under test that happens to have a List field.

However, your class's toString method calls the iterator() method, which is not 
implemented in EV's dynamic List instance.

Fortunately, this is easily solved by giving EqualsVerifier pre-fabricated 
values for List. In fact, EV already contains many such values for many common 
Java API classes--including ArrayList. However, List is still missing from the 
list.

For now, you can work around the issue by manually giving EqualsVerifier two 
List instances, like this:

    List<Integer> one = new ArrayList<Integer>();
    one.add(1);
    List<Integer> two = new ArrayList<Integer>();
    one.add(2);

    EqualsVerifier.forClass(SomeClass.class)
        .withPrefabValues(List.class, one, two)
        .verify();

Unfortunately, the lists have to be un-equal to each other, so this solution is 
a little verbose. (Incidentally, if you use Google Guava, you can cut down on 
this verbosity a little.)

I will fix this in the next release of EqualsVerifier. I can't make a promise 
about when that will be, though.

Original comment by [email protected] on 30 Nov 2011 at 9:48

  • Changed state: Accepted
  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

Thanks for the workaround. BTW, class Set is missing as well.

Original comment by [email protected] on 1 Dec 2011 at 8:19

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

You're welcome. And you're right, Set is missing, and so are Map and Collection.

Original comment by [email protected] on 1 Dec 2011 at 12:10

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

Issue 54 has been merged into this issue.

Original comment by [email protected] on 23 Jan 2012 at 6:58

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

It's fixed. Version 1.1 is available now.

Original comment by [email protected] on 11 Feb 2012 at 11:49

  • Changed state: Fixed
  • Added labels: ****
  • Removed labels: ****

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant