Я новичок в имитации объектов, но понимаю, что мне нужно, чтобы мои классы реализовывали интерфейсы, чтобы имитировать их.
Проблема, с которой я столкнулся, заключается в том, что на моем уровне доступа к данным я хочу иметь статические методы, но я не могу поместить статический метод в интерфейс.
Как лучше всего обойти это? Должен ли я просто использовать методы экземпляра (что кажется неправильным) или есть другое решение?





Я бы использовал шаблон объекта метода. Создайте статический экземпляр этого и вызовите его в статическом методе. Должна существовать возможность создания подкласса для тестирования, в зависимости от вашей имитирующей среды.
т.е. в вашем классе со статическим методом есть:
private static final MethodObject methodObject = new MethodObject();
public static void doSomething(){
methodObject.doSomething();
}
и ваш объект метода может быть очень простым и легко тестируемым:
public class MethodObject {
public void doSomething() {
// do your thang
}
}
Эээ, на самом деле нет. Я не уверен, придумал ли я это имя, или это считается скорее идиомой, чем шаблоном, но я не вижу никаких достойных ссылок от Google. Хотя буду продолжать искать.
Спасибо, пример помог мне понять, что вы имели в виду.
Это фактически убивает всякую идею о статических методах.
разве это не называется синглтоном?
Да, вы используете методы экземпляра. Статические методы в основном говорят: «Есть один способ реализовать эту функциональность - он не полиморфен». Издевательство основано на полиморфизме.
Теперь, если ваши статические методы логически не заботятся о том, какую реализацию вы используете, они могут принимать интерфейсы в качестве параметров или, возможно, работать без взаимодействия с состоянием вообще, но в противном случае вам следует использовать экземпляры (и, вероятно, внедрение зависимости, чтобы связать все вместе).
По возможности используйте методы экземпляра.
Используйте общедоступные статические функции Func [T, U] (ссылки на статические функции, которые могут быть заменены фиктивными функциями), где методы экземпляра невозможны.
Возможно, вы пытаетесь начать тестирование слишком глубоко. Нет необходимости создавать тест для проверки каждого метода в отдельности; частные и статические методы следует тестировать, вызывая общедоступные методы, которые затем по очереди вызывают частные и статические методы.
Допустим, ваш код выглядит так:
public object GetData()
{
object obj1 = GetDataFromWherever();
object obj2 = TransformData(obj1);
return obj2;
}
private static object TransformData(object obj)
{
//Do whatever
}
Вам не нужно писать тест для метода TransformData (и вы не можете). Вместо этого напишите тест для метода GetData, который проверяет работу, выполненную в TransformData.
Я нашел блог через гугл с отличными примерами того, как это сделать:
Класс рефакторинга должен быть классом экземпляра и реализовывать интерфейс.
Вы уже заявили, что не хотите этого делать.
Используйте класс экземпляра оболочки с делегатами для членов статических классов
Таким образом вы можете смоделировать статический интерфейс через делегатов.
Используйте класс экземпляра оболочки с защищенными членами, которые вызывают статический класс
Это, вероятно, самый простой способ имитировать / управлять без рефакторинга, поскольку его можно просто унаследовать и расширить.
Простое решение - разрешить изменение реализации статического класса через сеттер:
class ClassWithStatics {
private IClassWithStaticsImpl implementation = new DefaultClassWithStaticsImpl();
// Should only be invoked for testing purposes
public static void overrideImplementation(IClassWithStaticsImpl implementation) {
ClassWithStatics.implementation = implementation;
}
public static Foo someMethod() {
return implementation.someMethod();
}
}
Итак, при настройке ваших тестов вы вызываете overrideImplementation с каким-то имитацией интерфейса. Преимущество в том, что вам не нужно менять клиентов вашего статического класса. Обратной стороной является то, что у вас, вероятно, будет немного дублированный код, потому что вам придется повторять методы статического класса и его реализацию. Но иногда статические методы могут использовать более легкий интерфейс, который обеспечивает базовую функциональность.
Небольшой момент, разве не нужно было бы объявлять реализацию статической, если бы к ней можно было получить доступ статическим способом?
Проблема в том, что вы используете сторонний код и вызываете его из одного из ваших методов. В итоге мы обернули его в объект и передали его с помощью dep inj, а затем ваш модульный тест может имитировать сторонний статический метод, вызывая с ним сеттер.
Есть ли у вас какие-нибудь хорошие ссылки на этот паттерн? Не знаю, как бы я это сделал.