JUnit Mockito当...然后来自对象数组

时间:2015-10-17 14:59:46

标签: java arrays junit mockito

我试图使用mockito的when .... then函数。我想知道是否可以为当时部分列出一个列表,但是它要遍历列表并返回另一个对象。所以,如果我有一个包含3个对象的列表:A,B,C

我希望能够遍历列表并返回列表中的下一个对象。因此,如果when内部的方法被调用3次,则第一次返回A,第二次返回B,第三次返回C.这是我当前的代码:

public class fooTest  {
    private Foo foo;
    private List<Car> cars;
    private TestHelper helper;
    @Mock
    private DomainService service;
    private Car car;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);     
        foo = new Foo();
        helper = new TestHelper();
        cars = new ArrayList<Car>();
        Mockito.when(service.findObjectByID(any())).thenAnswer( AdditionalAnswers.returnsElementsOf(cars) );
    }

    @Test
    public void testVin() {
        cars = helper.generateCars(5, /*random number*/);
        Fleet result = foo.setFleet(Arrays.asList( helper.makeCars(3) );
        assertEquals(/*list of numbers*/, result.getCars().getVINs());
    }
}

public class TestHelper {
    public Fleet makeCars(int numCars) {
        Fleet fleet = new Fleet();
        Car car;
        for(int i=0; i<numCars; i++) {
            car = new Car(i, /*some vin number*/);
            fleet.add(car);
        }       

        return fleet;
    }
    public List<Car> generateCars(int numCars, int vinNum) {
        //implementation
    }
}

public class Foo {
    private DomainService domainService;

    // Constructor to initialize 

    public Fleet setFleet(List<Car> cars) {
        ....
        Optional<Vehicle> vehicle = domainService.findObjectByID(/*Some number*/);
        ....
    }
}

public class DomainService {
    Optional<Vehicle> findObjectByID(long id) {
        //implementation
    }
}

车辆是汽车延伸的类。我的问题是每次findObjectByID被调用vehicle对象为空。这是有道理的,因为cars对象被初始化为空列表,而mockito when函数使用它作为返回列表而不是在测试函数中生成的填充列表。我也得到了这个运行时错误:

java.lang.ClassCastException: com.jer.test.model.Car cannot be cast to com.google.common.base.Optional

但我已经改变了我的代码并尝试了这种方式:

@Before
public void setUp() throws Exception {
}

@Test
public void testVin() {
    cars = helper.generateCars(5, /*random number*/);
    Mockito.when(service.findObjectByID(any())).thenAnswer( AdditionalAnswers.returnsElementsOf(cars) );
    Fleet result = foo.setFleet(Arrays.asList( helper.makeCars(3) );
    assertEquals(/*list of numbers*/, result.getCars().getVINs());
}

但是vehicle对象仍为空。我不知道为什么。我出错了哪个地方?

重新尝试1:我已经尝试了以下但没有运气:

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);     
    foo = new Foo();
    helper = new TestHelper();        
}

@Test
public void testVin() {
    cars = helper.generateCars(5, /*random number*/);
    Mockito.when(service.findObjectByID(any())).then( new ReturnsElementsOf(bFIs) );
    Fleet result = foo.setFleet(Arrays.asList( helper.makeCars(3) );
    assertEquals(/*list of numbers*/, result.getCars().getVINs());
}

重新尝试2:我已经尝试了以下运气:

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);     
    foo = new Foo();
    helper = new TestHelper();
    cars = new ArrayList<Car>();
    cars.add(new Car(1, 2));
    Mockito.when(service.findObjectByID(any())).thenAnswer( AdditionalAnswers.returnsElementsOf(cars) );
}

@Test
public void testVin() {
    cars = helper.generateCars(5, /*random number*/);
    Fleet result = foo.setFleet(Arrays.asList( helper.makeCars(3) );
    assertEquals(/*list of numbers*/, result.getCars().getVINs());
}

这似乎有效。返回的车辆对象是在setUp类中制作的汽车对象,但这并不是我想要的,因为我希望返回来自列表或不同的汽车对象。

重新尝试3:我已经尝试了Florian Schaetz的建议,但是当findObjectByID被调用时,我仍然会返回null:

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);     
    foo = new Foo();
    helper = new TestHelper();

}

@Test
public void testVin() {
    cars = helper.generateCars(5, /*random number*/);
    for(Car car : cars) {
        Mockito.when(service.findObjectByID(any())).thenReturn( Optional.of(car) );
    }
    Fleet result = foo.setFleet(Arrays.asList( helper.makeCars(3) );
    assertEquals(/*list of numbers*/, result.getCars().getVINs());
}

1 个答案:

答案 0 :(得分:2)

为sequentiel调用返回不同的东西实际上非常简单......

Mockito.when( <some mock invocation>).thenReturn( a ).thenReturn( b).thenReturn( c );

这将为第一次调用返回a,为第二次调用返回b,为后面的所有其他人返回c

如果你不知道有多少,你可以使用Answer就像你试过的那样(很简单),但也可以像这样包装......

OngoingStubbing<T> stubbing = Mockito.when ( <something> );
for(Object obj : array) {
 stubbing = stubbing.then( obj );
}

另一方面,我真的不明白为什么你需要写一个你不知道返回值是什么的UnitTest ......如果你问我,那就有一些代码味道。< / p>

对某些事情进行随机测试可能是一个好主意,但老实说,我不会用它来存根。

无论如何,为什么要使用Mockito.when(service.findObjectByID(any()))?这不是你问题的根源吗?如果你必须创建随机汽车(我怀疑它),那么写起来很容易......

List<Car> cars = helper.generateCars(5, /*random number*/);
for(Car car : cars) {
    Mockito.when(service.findObjectByID(car.getId())).thenReturn(car);
}