hardayal / hamcrest

Automatically exported from code.google.com/p/hamcrest
0 stars 0 forks source link

IsCollectionContaining doesn't support subtypes #24

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I posted this in the forum but now I realize I should have opened a request:

There appears to be a problem with the IsCollectionContaining class
which I am surprised hasn't hit a few people: here is an example of
what I want to do:

import static org.hamcrest.collection.IsCollectionContaining.hasItem;
import static org.junit.Assert.assertThat;

  @Test
  public void testSuperClass() throws Exception
  {
    final Set<Number> s = new HashSet<Number>();
    s.add(Integer.valueOf(2));
    assertThat(s, hasItem(Integer.valueOf(2)));
  }

however the above code doesn't compile becuase Integer is not Number.
The only workaraound at the moment is as follows which I think you
will agree is less than ideal.

  @Test
  public void testSuperClass() throws Exception
  {
    final Set<Number> s = new HashSet<Number>();
    s.add(Integer.valueOf(2));
    assertThat(s,
IsCollectionContaining.<Number>hasItem(Integer.valueOf(2)));
  }

There is a much neater solution. We need to change the
IsCollectionContaining class as follows:

package org.hamcrest.collection;

import static org.hamcrest.core.AllOf.allOf;
import static org.hamcrest.core.IsEqual.equalTo;

import java.util.ArrayList;
import java.util.Collection;

import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

public class IsCollectionContaining<T> extends
TypeSafeMatcher<Iterable<? super T>>
{
  private final Matcher<? extends T> elementMatcher;

  public IsCollectionContaining(final Matcher<? extends T>
elementMatcher)
  {
    this.elementMatcher = elementMatcher;
  }

  @Override
  public boolean matchesSafely(final Iterable<? super T> collection)
  {
    for (final Object item : collection)
    {
      if (elementMatcher.matches(item))
      {
        return true;
      }
    }
    return false;
  }

  public void describeTo(final Description description)
  {
    description.appendText("a collection containing
").appendDescriptionOf(elementMatcher);
  }

  @Factory
  public static <T> Matcher<Iterable<? super T>> hasItem(final
Matcher<? extends T> elementMatcher)
  {
    return new IsCollectionContaining<T>(elementMatcher);
  }

  @Factory
  public static <T> Matcher<Iterable<? super T>> hasItem(final T
element)
  {
    return hasItem(equalTo(element));
  }

  @Factory
  public static <T> Matcher<Iterable<? super T>> hasItems(final
Matcher<? extends T>... elementMatchers)
  {
    final Collection<Matcher<? extends Iterable<? super T>>> all = new
ArrayList<Matcher<? extends Iterable<? super T>>>(
        elementMatchers.length);
    for (final Matcher<? extends T> elementMatcher : elementMatchers)
    {
      all.add(hasItem(elementMatcher));
    }
    return allOf(all);
  }

  @Factory
  public static <T> Matcher<Iterable<? super T>> hasItems(final T...
elements)
  {
    final Collection<Matcher<? extends Iterable<? super T>>> all = new
ArrayList<Matcher<? extends Iterable<? super T>>>(
        elements.length);
    for (final T element : elements)
    {
      all.add(hasItem(element));
    }
    return allOf(all);
  }
} 

Original issue reported on code.google.com by NikolayM...@gmail.com on 12 Nov 2007 at 9:17

GoogleCodeExporter commented 8 years ago
Is this expected to be released with JUnit in the near future?

While we're at it, it would be nice to be able to specify a collection as a 
parameter to hasItem.

    @Factory 
    public static <T> Matcher<Iterable<? super T>> hasItem(final Collection<? extends T> elements) {
        final Collection<Matcher<? extends Iterable<? super T>>> all = new ArrayList<Matcher<? extends 
Iterable<? super T>>>(elements.size());
        for (final T element : elements) {
            all.add(hasItem(element));
        }
        return allOf(all);
    }

Original comment by newsju...@gmail.com on 23 Feb 2008 at 8:39

GoogleCodeExporter commented 8 years ago
Fixed as part of larger generics changes

Original comment by smgfree...@gmail.com on 20 Nov 2008 at 4:42

GoogleCodeExporter commented 8 years ago

Original comment by smgfree...@gmail.com on 22 Nov 2008 at 12:20