Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中测试泛型列表是否包含子类型的确切子集合?_Java_Generics_Collections_Junit_Bounded Wildcard - Fatal编程技术网

如何在Java中测试泛型列表是否包含子类型的确切子集合?

如何在Java中测试泛型列表是否包含子类型的确切子集合?,java,generics,collections,junit,bounded-wildcard,Java,Generics,Collections,Junit,Bounded Wildcard,我有一个抽象类AbstractService和几个扩展这个抽象类的类: 然后,我有一个ServiceFactory,它根据我传递的参数返回一些服务的通用列表: public class ServiceFactory { public List<? extends AbstractService> getServices(final MyParameter param) { // Service is an interface implemented by A

我有一个抽象类AbstractService和几个扩展这个抽象类的类:

然后,我有一个ServiceFactory,它根据我传递的参数返回一些服务的通用列表:

public class ServiceFactory {
    public List<? extends AbstractService> getServices(final MyParameter param) {
        // Service is an interface implemented by AbstractService
        List<Service> services = new ArrayList<>();

        for (Foo foo : param.getFoos()) {
            services.add(new AService(foo.getBar()));
        }
        // creates the rest of the services
        return services;
    }
}
公共类服务工厂{

public List毫无疑问,AService的子类型是AService的实例,返回true的条件是正确的

甚至没有一种使用循环实现它的好方法,这在很大程度上取决于执行上下文,从不同类装入器装入的“相同”类是“不同”的


我会退一步考虑您希望验证的服务的属性,该属性是否应该在AbstractService?中定义,最后使用该属性验证结果。

您可以使用hamcrest Matchers

包含用于检查集合/可编辑内容的匹配器

我希望以下示例与您的szenario匹配

import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.hamcrest.Matchers.containsInAnyOrder;

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

import org.apache.commons.lang.builder.EqualsBuilder;

import org.junit.Test;

public class ServiceFactoryTest
{
    @Test
    public void serviceFactoryShouldReturnAServiceForEachFoo()
    {
        Foo foo = mock( Foo.class );
        Service service = new AService( foo );
        Service[] expected = { service, service, service };
        Service[] tooFew = { service, service };
        Service[] tooMany = { service, service, service, service };

        ServiceFactory factory = new ServiceFactory();

        assertThat( factory.createServices( foo, foo, foo ), containsInAnyOrder( expected ) );
        assertThat( factory.createServices( foo, foo, foo ), not( containsInAnyOrder( tooFew ) ) );
        assertThat( factory.createServices( foo, foo, foo ), not( containsInAnyOrder( tooMany ) ) );
    }

    interface Foo
    {}

    interface Service
    {}

    class AService implements Service
    {
        Foo foo;

        public AService( Foo foo )
        {
            this.foo = foo;
        }

        @Override
        public boolean equals( Object that )
        {
            return EqualsBuilder.reflectionEquals( this, that );
        }
    }

    class ServiceFactory
    {
        Collection<? extends Service> createServices( Foo... foos )
        {
            Collection<Service> list = new ArrayList<>();

            for ( Foo foo : foos )
            {
                list.add( new AService( foo ) );
            }

            return list;
        }
    }
}
导入静态org.hamcrest.CoreMatchers.not;
导入静态org.hamcrest.matcherasert.assertThat;
导入静态org.mockito.mockito.mock;
导入静态org.hamcrest.Matchers.containsInAnyOrder;
导入java.util.ArrayList;
导入java.util.Collection;
导入org.apache.commons.lang.builder.EqualsBuilder;
导入org.junit.Test;
公共类ServiceFactoryTest
{
@试验
public void ServiceFactory应返回AserviceForEachFoo()
{
Foo-Foo=mock(Foo.class);
服务=新的AService(foo);
服务[]应为{服务,服务,服务};
服务[]TooNow={Service,Service};
Service[]tooMany={Service,Service,Service,Service};
ServiceFactory工厂=新的ServiceFactory();
资产(factory.createServices(foo,foo,foo),包含任何订单(预期));
资产(factory.createServices(foo,foo,foo),而不是(containsInAnyOrder(toonow));
资产(factory.createServices(foo,foo,foo),而不是(containsInAnyOrder(tooMany));
}
接口Foo
{}
接口服务
{}
类AService实现服务
{
富富,;
公共AService(Foo-Foo)
{
this.foo=foo;
}
@凌驾
公共布尔等于(该对象)
{
返回EqualsBuilder.reflectionEquals(这个,那个);
}
}
类服务工厂
{

收藏非常感谢Max Fichtelmann为我指明了正确的方向

我最终开始使用,但Hamcrest可能也能达到同样的效果

我创建了一个自定义匹配器,
assertEvery
,比较列表大小:

public class ServiceAssert extends AbstractAssert<ServiceAssert, List<Service>> {
  public ServiceAssert(List<Service> actual) {
    super(actual, ServiceAssert.class);
  }

  // it's usually assertThat, but it conflicts with the List<T> assertions
  public static ServiceAssert assertThatMy(List<Service> actual) {
    return new ServiceAssert(actual);
  }

  public ServiceAssert containsEvery(List<? extends Service> expectedServices) {
    Integer listSize = 0;

    isNotNull();

    if (expectedServices == null || expectedServices.isEmpty()) {
      throw new AssertionError("Do not use this method for an empty or null list of services, use doesNotContain instead.");
    }

    Class<? extends Service> serviceClass = expectedServices.get(0).getClass();

    for (Service f : actual) {
      if (f.getClass().equals(serviceClass)) {
        listSize++;
      }
    }

    if (listSize != expectedServices.size()) {
      throw new AssertionError("expected " + expectedServices.size() + " " + serviceClass.getSimpleName() + " but was " + listSize + ".");
    }

    return this;
  }
}
公共类ServiceAssert扩展了AbstractAssert{
公共服务断言(实际列表){
super(实际的,ServiceAssert.class);
}
//通常是assertThat,但它与列表断言冲突
公共静态服务assertThatMy(实际列表){
返回新的ServiceAssert(实际);
}

公共服务(列表我将使用Set,并可能检查以下内容:您的示例代码正确吗?您将3个相同的内容放入您的
expectedServices
列表中。您是否希望计算列表中不同类的数量,以查看该数字是否为3?@DanGetz不完全正确。在我的应用程序中,我根据另一段将这些服务添加到列表中meter,所以服务并不都是相同的,它们并不总是返回3。但是在我的单元测试中,我使用模拟参数来获得预期的结果。谢谢你的回答!但是我不是在测试我的AService类,而是一个返回服务列表的工厂。我将改进我的问题。我尝试了你的答案,但是当列表中有更多类型的服务(例如,另一种服务)。尽管如此,我还是应该使用really learn这些匹配器。在这种情况下,您可能应该在这个测试中声明大小,并在自己的测试中测试正确的服务创建,比如createFooServiceForFoo()和createBarServiceForBar().contains/containsInAnyOrder匹配器还接受一组匹配器,因此您可以使用instanceOf(Class)匹配器而不是equals检查。
public class ServiceAssert extends AbstractAssert<ServiceAssert, List<Service>> {
  public ServiceAssert(List<Service> actual) {
    super(actual, ServiceAssert.class);
  }

  // it's usually assertThat, but it conflicts with the List<T> assertions
  public static ServiceAssert assertThatMy(List<Service> actual) {
    return new ServiceAssert(actual);
  }

  public ServiceAssert containsEvery(List<? extends Service> expectedServices) {
    Integer listSize = 0;

    isNotNull();

    if (expectedServices == null || expectedServices.isEmpty()) {
      throw new AssertionError("Do not use this method for an empty or null list of services, use doesNotContain instead.");
    }

    Class<? extends Service> serviceClass = expectedServices.get(0).getClass();

    for (Service f : actual) {
      if (f.getClass().equals(serviceClass)) {
        listSize++;
      }
    }

    if (listSize != expectedServices.size()) {
      throw new AssertionError("expected " + expectedServices.size() + " " + serviceClass.getSimpleName() + " but was " + listSize + ".");
    }

    return this;
  }
}