我还在学习模拟,现在我正在学习如何注射嘲笑。
我有一个正在测试的对象,它使用一种依赖于其他对象的特定方法。反过来,这些对象依赖于其他对象。我想嘲笑某些事情并在执行过程中随处使用这些模拟 - 在整个方法的控制流程中。
例如,假设有类似的类:
public class GroceryStore {
public double inventoryValue = 0.0;
private shelf = new Shelf(5);
public void takeInventory() {
for(Item item : shelf) {
inventoryValue += item.price();
}
}
}
public class Shelf extends ArrayList<Item> {
private ProductManager manager = new ProductManager();
public Shelf(int aisleNumber){
super(manager.getShelfContents(aisleNumber);
}
}
public class ProductManager {
private Apple apple;
public void setApple(Apple newApple) {
apple = newApple;
}
public Collection<Item> getShelfContents(int aisleNumber) {
return Arrays.asList(apple, apple, apple, apple, apple);
}
}
我需要编写带有以下部分的测试代码:
....
@Mock
private Apple apple;
...
when(apple.price()).thenReturn(10.0);
...
...
@InjectMocks
private GroceryStore store = new GroceryStore();
...
@Test
public void testTakeInventory() {
store.takeInventory();
assertEquals(50.0, store.inventoryValue);
}
每当调用apple.price()时,我都希望我的模拟苹果成为使用过的苹果。这可能吗?
编辑:
重要提示......
包含我想要模拟的对象的类确实有一个该对象的setter。但是,在我正在测试的级别上,我并没有真正掌握该类。因此,按照这个例子,虽然ProductManager有一个Apple的setter,但是我没办法从GroceryStore对象中获取ProductManager。
答案 0 :(得分:2)
问题是您通过调用new
而不是注入它来创建您所依赖的对象。将ProductManager
注入Shelf
(例如在构造函数中),并将Shelf
注入GroceryStore
。然后在测试中使用模拟。如果你想使用@InjectMocks
,你必须通过setter方法注入。
通过构造函数,它看起来像这样:
public class GroceryStore {
public double inventoryValue = 0.0;
private shelf;
public GroceryStore(Shelf shelf) {
this.shelf = shelf;
}
public void takeInventory() {
for(Item item : shelf) {
inventoryValue += item.price();
}
}
}
public class Shelf extends ArrayList<Item> {
private ProductManager manager;
public Shelf(int aisleNumber, ProductManager manager) {
super(manager.getShelfContents(aisleNumber);
this.manager = manager;
}
}
public class ProductManager {
private Apple apple;
public void setApple(Apple newApple) {
apple = newApple;
}
public Collection<Item> getShelfContents(int aisleNumber) {
return Arrays.asList(apple, apple, apple, apple, apple);
}
}
然后你可以测试它模仿你所依赖的所有对象:
@Mock
private Apple apple;
...
when(apple.price()).thenReturn(10.0);
@InjectMocks
private ProductManager manager = new ProductManager();
private Shelf shelf = new Shelf(5, manager);
private GroceryStore store = new GroceryStore(shelf);
//Then you can test your store.