4

我仍在学习模拟,现在我正在学习如何注入模拟。

我有一个正在测试的对象,它使用依赖于其他对象的特定方法。反过来,这些对象依赖于其他对象。我想模拟某些东西,并在执行过程中到处使用这些模拟——在方法的控制流中。

例如假设有如下类:

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() 时,我都希望使用我的模拟苹果。这可能吗?

编辑:
重要说明...
包含我要模拟的对象的类确实有该对象的设置器。但是,在我正在测试的级别上,我并没有真正掌握该课程。所以,按照这个例子,虽然 ProductManager 有一个用于 Apple 的设置器,但我没有办法从 GroceryStore 对象中获取 ProductManager。

4

1 回答 1

2

new问题是您通过调用而不是注入来创建您依赖的对象。注入(例如在构造函数中),并ProductManager注入. 然后在测试中使用模拟。如果要使用,则必须通过 setter 方法注入。ShelfShelfGroceryStore@InjectMocks

通过构造函数,它可能如下所示:

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.
于 2010-11-03T10:08:08.820 回答