Mockito: впрыскивание издевательств во всем потоке управления - PullRequest
4 голосов
/ 15 октября 2010

Я все еще изучаю мокито, и сейчас я учусь делать инъекции.

У меня есть тестируемый объект с определенным методом, который зависит от других объектов. Эти объекты, в свою очередь, зависят от других объектов. Я хочу издеваться над некоторыми вещами и использовать их во время выполнения - во всем потоке управления метода.

Например, предположим, что есть классы вроде:

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 (), я хочу, чтобы использовалось мое фиктивное яблоко. Это возможно?

EDIT:
Важное замечание ...
класс, который содержит объект, который я хочу смоделировать, имеет установщик для этого объекта. Тем не менее, я не имею никакого отношения к этому классу на уровне, который я тестирую. Итак, следуя примеру, хотя в ProductManager есть установщик для Apple, у меня нет способа получить ProductManager из объекта GroceryStore.

1 Ответ

2 голосов
/ 03 ноября 2010

Проблема в том, что вы создаете объекты, от которых зависите, вызывая new, а не вводя его.Введите ProductManager в Shelf (например, в конструкторе) и введите Shelf в GroceryStore.Затем в тесте используют макеты.Если вы хотите использовать @InjectMocks, вы должны внедрить с помощью методов установки.

По конструктору это может выглядеть так:зависит от:

@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.
...