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

标签 java generics collections junit bounded-wildcard

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

Silly class diagram

然后,我有一个 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;
    }
}

在我的 UnitTest 中,我想验证我的服务列表是否恰好包含 3 个 AService 子类型。我现在的做法是:

@Test
public void serviceFactoryShouldReturnAServiceForEachFoo() {
  // I'm mocking MyParameter and Foo here
  Mockito.when(param.getFoos()).thenReturn(Arrays.asList(foo, foo, foo);

  AService aservice = new AService(foo);

  List<AService> expectedServices = Arrays.asList(aservice, aservice, aservice);
  List<? extends AbstractService> actualServices = serviceFactory.getServices();

  assertTrue(CollectionUtils.isSubCollection(expectedServices, actualServices));
}

当actualServices包含少于3个Aservice时,测试正确失败。这个解决方案的唯一问题是,如果actualServices包含超过3个AService,则测试通过......

是否有一种方法可以做到这一点,或者我应该使用循环自己实现它?

最佳答案

您可以使用 hamcrest Matchers。

hamcrest-library包含匹配器来检查集合/可迭代内容。

我希望以下示例与您的场景大致匹配

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;
        }
    }
}

关于java - 如何测试泛型列表是否包含 Java 中子类型的确切子集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21284859/

相关文章:

java - Kotlin 错误 : 'public' function exposes its 'public/*package*/' return type argument

ios - 如何避免索引超出范围的错误?

ArrayList 中的 Java 排序对象

java - 如何使用流实现 hashmap 的 isEmpty() ?

Scala 泛型 < : and multiple traits

ios - 如何检查通用 swift 数组包含一个元素?

c# - .NET 中的随机和线程问题

java - 无法使用 Thymeleaf/Spring-Boot 迭代 List<List<String>>

java - Spring DeferredResult 导致 IOException : An established connection was aborted by the software in your host machine

java - 根据jsp中的输入选择表