2008-09-30 9 views
34

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

Проблема, с которой я сталкиваюсь, заключается в том, что на моем уровне доступа к данным я хочу иметь статические методы, но я не могу поместить статический метод в интерфейс.

Каков наилучший способ обойти это? Должен ли я просто использовать методы экземпляра (что кажется неправильным) или есть другое решение?

ответ

22

Я использовал бы метод объекта узор. Имейте статический экземпляр этого и вызовите его в статическом методе. Это должно быть возможным для подкласса для тестирования, в зависимости от вашей издевательской структуры.

т.е. в классе со статическим методом есть:

private static final MethodObject methodObject = new MethodObject(); 

public static void doSomething(){ 
    methodObject.doSomething(); 
} 

и ваш объект метод может быть очень простой, легко проверены:

public class MethodObject { 
    public void doSomething() { 
     // do your thang 
    } 
} 
+0

У вас есть хорошие ссылки для этого шаблона? Я не знаю, как это сделать. – brien 2008-09-30 13:56:02

+0

Err, нет. Я не уверен, что я сделал это имя, или он считается более идиомой, чем шаблон, но я не вижу никаких достойных ссылок от Google. Будем продолжать смотреть. – Grundlefleck 2008-09-30 14:05:06

23

Да, вы используете методы экземпляра , Статические методы в основном говорят: «Существует один способ выполнить эту функцию - это не полиморфно». Издевательский полагается на полиморфизм.

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

4

Используйте методы экземпляра, где это возможно.

Использовать общедоступный статический Func [T, U] (ссылки на статические функции, которые можно заменить макетными функциями), где методы экземпляра невозможны.

5

Возможно, вы пытаетесь проверить слишком глубокую отправную точку. Тест не нужно создавать, чтобы тестировать каждый метод индивидуально; частные и статические методы должны быть протестированы, вызывая общедоступные методы, которые затем вызывают частные и статические в свою очередь.

Так позволяет сказать, что ваш код выглядит так:

public object GetData() 
{ 
object obj1 = GetDataFromWherever(); 
object obj2 = TransformData(obj1); 
return obj2; 
} 
private static object TransformData(object obj) 
{ 
//Do whatever 
} 

Вам не нужно написать тест против метода TransformData (и вы не можете). Вместо этого напишите тест для метода GetData, который проверяет работу, проделанную в TransformData.

25

Я нашел blog via google с некоторыми большими примерами о том, как это сделать:

  1. рефакторинга класс быть экземпляр класса и реализации интерфейса.

    Вы уже заявили, что не хотите этого делать.

  2. Используйте обертка экземпляр класса с делегатами для статических классов членов

    Делая это, вы можете моделировать статический интерфейс с помощью делегатов.

  3. Используйте класс экземпляра обертки с защищенными членами, которые требуют статического класса

    Это, вероятно, самое простым глумиться/обойтись без рефакторинга, как это только может быть унаследовано от и продлено.

1

Простое решение, чтобы изменить реализацию статического класса с помощью сеттер:

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, который обеспечивает базовую функциональность.

0

Проблема у вас есть, когда вы используете сторонний код и вызывается одним из ваших методов. То, что мы закончили, - это обернуть его в объект и вызвать передачу его с помощью dep inj, а затем ваш модульный тест может издеваться над сторонним статическим методом, вызывая его с помощью setter.