Судя по вашему разрешению, вы больше ссылаетесь на "издевательство", как на заглушение некоторых тестовых данных.Это всегда отличный способ продвинуться вперед в разработке, когда вы больше озабочены функциональностью и не особо заботитесь о специфике.
Так что я просто даю вам этот ответ, потому что вы сказали, что вы новичокна модульное тестирование.Поэтому, если вы писали модульный тест, который зависел от ProductsDatasource , вы могли бы также использовать инфраструктуру Mocking для подключения «фиктивного» объекта вместо того, чтобы заглушить конкретный класс.Я больше работаю с .Net, чем с Java, но все мои примеры кода будут использовать JUnit и JMock для описания того, о чем я говорю.Помните, что интерфейс - это просто контракт, в котором говорится, что ваш класс будет предоставлять указанные методы.
Допустим, у вас есть реализация интерфейса ProductsDatasource, например:
public interface IProductsDatasource {
public List<Product> getProducts();
}
И конкретный тип:
public class ProductsDatasource implements IProductsDatasource {
private List<Product> mProducts;
public ProductsDatasource(List<Product> products) {
mProducts = products;
}
public List<Product> getProducts() {
return mProducts;
}
}
Теперь, скажем, вы что-то тестируете, скажем TargetAdapter , который принимает ProductsDatasource .Если вы создадите новый ProductsDatasource , у вас будет зависимость.Ваш модульный тест теперь будет зависеть от класса, который вы тестируете, и ProductsDatasource .Возможно, вы уже тестировали ProductsDatasource в другом наборе.
public class TargetAdapter {
private IProductsDatasource mDatasource;
public TargetAdapter(IProductsDatasource datasource) {
mDatasource = datasource;
}
public List<Product> products() {
return mDatasource.getProducts();
}
}
Итак, вот контрольный пример без насмешек, который подробно описывает то, о чем я говорю.
@Test
public void TargetAdapterReturnsProducts() {
List<Product> data = new ArrayList<Product>();
data.add(new Product("Sample Product 1"));
data.add(new Product("Sample Product 2"));
data.add(new Product("Sample Product 3"));
TargetAdapter adapter = new TargetAdapter(new ProductsDatasource(data)); // See the dependency
List<Product> products = adapter.products();
Assert.assertNotNull(adapter);
Assert.assertTrue(products.size() == 3);
}
Итак, чтобы проверить мой адаптер, мне нужно создать новый адаптер и новый источник данных.Меня не волнует источник данных, мне просто нужно убедиться, что мой адаптер выполняет то, что я намеревался сделать.Mocking позволяет мне тестировать мой адаптер изолированно, указав тип интерфейса и настроив, как я хочу, чтобы он себя вел.Теперь я не привязан к конкретной реализации класса для тестирования моего адаптера.
Итак, вот пример, где я использую JMock для создания фиктивного источника данных:
@Test
public void MockingTest() {
final Mockery context = new Mockery();
final List<Product> mockData = new ArrayList<Product>();
mockData.add(new Product("Sample Product 1"));
mockData.add(new Product("Sample Product 2"));
mockData.add(new Product("Sample Product 3"));
final IProductsDatasource mockDatasource = context.mock(IProductsDatasource.class);
context.checking(new Expectations(){{
oneOf (mockDatasource).getProducts(); will(returnValue(mockData)); // This is where I tell JMock to return my test data when getProducts() is called
}});
TargetAdapter adapter = new TargetAdapter(mockDatasource); // No dependency ;)
List<Product> products = adapter.products();
Assert.assertNotNull(adapter);
Assert.assertTrue(products.size() == 3);
}
Так как выЯ сказал, что вы новичок в модульном тестировании, и я хотел бы указать на мощь объектов Mock в модульном тестировании и на то, как вы можете использовать их для написания лучшего кода.Вы также можете настроить фиктивные объекты, чтобы убедиться, что ваш целевой объект вызывает метод в вашей имитации.Я часто это использую, когда меня не интересует реализация метода или результата, я просто хочу убедиться, что мой класс вызывает его, когда это необходимо.Теперь, чтобы все это работало, вы должны использовать интерфейсы, но довольно просто сделать refactor -> extract interface
Я запустил все это в eclipse, прежде чем опубликовать его, поэтому кодработает, если вы хотите поиграть с ним.Надеюсь, это поможет!