Как насмехаться со статическими методами?
Я новичок в подделке объектов, но я понимаю, что мне нужно, чтобы мои классы реализовали интерфейсы, чтобы имитировать их.
Проблема, с которой я сталкиваюсь, заключается в том, что на моем уровне доступа к данным я хочу иметь статические методы, но я не могу поместить статический метод в интерфейс.
Какой лучший способ? Должен ли я просто использовать методы экземпляра (что кажется неправильным) или есть другое решение?
Ответы
Ответ 1
Я бы использовал шаблон объекта метода. Имейте статический экземпляр этого и вызовите его в статическом методе. Это должно быть возможным для подкласса для тестирования, в зависимости от вашей издевательской структуры.
то есть. в вашем классе со статическим методом:
private static final MethodObject methodObject = new MethodObject();
public static void doSomething(){
methodObject.doSomething();
}
и ваш объект метода может быть очень простым, легко протестированным:
public class MethodObject {
public void doSomething() {
// do your thang
}
}
Ответ 2
Я нашел блог через google с некоторыми замечательными примерами о том, как это сделать:
-
Класс refactor должен быть классом экземпляра и реализовывать интерфейс.
Вы уже заявили, что не хотите этого делать.
-
Используйте класс экземпляра оболочки с делегатами для членов статических классов.
Выполняя это, вы можете имитировать статический интерфейс через делегатов.
-
Используйте класс экземпляра-оболочки с защищенными членами, которые вызывают статический класс
Это, пожалуй, самый простой способ издеваться/управлять без рефакторинга, поскольку он может просто наследоваться и расширяться.
Ответ 3
Да, вы используете методы экземпляра. Статические методы в основном говорят: "Существует один способ выполнить эту функцию - это не полиморфно". Издевательский полагается на полиморфизм.
Теперь, если ваши статические методы логически не заботятся о том, какую реализацию вы используете, они могут использовать интерфейсы в качестве параметров или, возможно, работать без взаимодействия с состоянием вообще, но в противном случае вы должны использовать экземпляры (и, возможно, инъекции зависимостей, чтобы соединить все вместе).
Ответ 4
Возможно, вы пытаетесь проверить слишком глубокую отправную точку. Тест не нужно создавать, чтобы тестировать каждый метод индивидуально; частные и статические методы должны быть протестированы, вызывая общедоступные методы, которые затем поочередно называют частным и статическим.
Итак, скажем, ваш код выглядит так:
public object GetData()
{
object obj1 = GetDataFromWherever();
object obj2 = TransformData(obj1);
return obj2;
}
private static object TransformData(object obj)
{
//Do whatever
}
Вам не нужно писать тест против метода TransformData (и вы не можете). Вместо этого напишите тест для метода GetData, который проверяет работу, выполненную в TransformData.
Ответ 5
Использовать методы экземпляра, где это возможно.
Использовать общедоступный static Func [T, U] (ссылки на статические функции, которые можно заменить макетными функциями), где методы экземпляра невозможны.
Ответ 6
Простое решение состоит в том, чтобы позволить изменять реализацию статического класса через сеттер:
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
с помощью какого-то издевавшегося интерфейса. Преимущество в том, что вам не нужно менять клиентов своего статического класса. Недостатком является то, что у вас, вероятно, будет небольшой дублированный код, потому что вам придется повторять методы статического класса и его реализации. Но иногда статические методы могут использовать интерфейс ligther, который обеспечивает базовую функциональность.
Ответ 7
Проблема заключается в том, что вы используете сторонний код и вызывается из одного из ваших методов. То, что мы закончили, - это обернуть его в объект и вызвать его с помощью dep inj, а затем ваш unit test может издеваться над сторонним статическим методом, вызывая с ним установщик.