Добавление статических методов для облегчения модульных тестов - хорошая практика? - PullRequest
3 голосов
/ 17 ноября 2011

Скажите, у меня есть этот класс:

class MyClass {
    private String s;
    // more attributes here
    public MyClass(String s, /*more constructor params*/)  {...}

    public String myMethod(String s) {
        //complex logic here
    }
}

Для модульного тестирования myMethod() Мне нужно создать весь объект (со многими параметрами, которые необходимо сконструировать и т. Д.), В то время как метод использует только s.

Альтернативно могу добавить статический метод:

class MyClass {
    private String s;
    // more attributes here
    public MyClass(String s, /*more constructor params*/)  {...}

    public String myMethod(String s) {
        return myStaticMethod(s);
    }

    public static myStaticMethod(String s) {
        //complex logic here
    }
}

Теперь я могу легко тестировать «сложную логику» без необходимости создавать объект. someStaticMethod(String s) не должно иметь побочных эффектов для класса. Поэтому я добавляю дополнительный метод только для удобства тестирования. Это хорошая практика?

Ответы [ 7 ]

5 голосов
/ 17 ноября 2011

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

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


Может быть что-то вроде этого:

class ComplexLogician {

  String myMethod(String a, String b) {
    /* Complex logic here. */
  }

}

class MyClass {

  private String s;

  private final ComplexLogician logic;

  /* More attributes here... */

  MyClass(String s, ComplexLogician logic, /* More parameters... */)  {...}

  String myMethod(String b) {
    return logic.myMethod(s, b);
  }

}
3 голосов
/ 17 ноября 2011

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

public class SampleTestSuite  {
    private MyClass myClass;

    @Before
    public void startUp(){
    myClass = new MyClass();//Will be called before each test method is called.

    }

    @Test
    public void testNavigationSucceeded() {
        assert...
    }

    @Test
    public void secondTest() {
        assert...
    }

    @After
    public void tearDown() {

    }

}
2 голосов
/ 18 ноября 2011

Изменение вашего производственного кода и раскрытие его «внутренностей», чтобы вы могли проверить его, является очень плохой практикой.Это нарушает инкапсуляцию, и, если ваш код не тестируется в первую очередь, это обычно означает, что он нуждается в рефакторинге.

«Сложная логика», которую вы хотите переместить в статическом методе, безусловно, принесет пользу для правильной обработки ОО., Создайте специальный класс для обработки этой логики или набор классов, внедрите их в ваш MyClass через интерфейс, разделите задачи, и ваше тестирование станет намного проще.

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

Пример: Допустим, вашMyClass необходимо сильно преобразовать один из его параметров (в вашем случае, String s, прежде чем его можно будет использовать. Итак, вы хотели извлечь эту обработку в статический метод? Вместо этого добавьте в свой класс зависимость,скажем, StringTransformer (переименуйте соответственно), который является интерфейсом к реальной реализации, которую вы хотите. В преобразователе есть метод transform(String s), который будет содержать желаемую логику. Затем протестируйте свою реализацию обычными способами, работа выполнена.И вы действительно сделали свой дизайн лучше.

2 голосов
/ 17 ноября 2011

Если метод может быть статическим, то он должен быть статическим, независимо от того, нужен ли он для тестирования или чего-то еще. Для этого вы можете включить предупреждения в Eclipse. Eclipse дает вам предупреждение о нестатических методах, которые могут быть статическими.

1 голос
/ 19 ноября 2011

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

0 голосов
/ 19 ноября 2011

Если вы тестируете только свой статический метод, то оставляете метод экземпляра открытым.Вместо этого вы можете изменить метод экземпляра, чтобы он мог быть протестирован.Если вы опубликуете более подробную информацию о конкретном случае здесь или в качестве нового вопроса, я уверен, что кто-то поможет вам сделать его тестируемым.

0 голосов
/ 18 ноября 2011

В общем, не рекомендуется выставлять какие-либо функции больше, чем ожидается от класса. Это помешало бы легко отойти от этой логики, поскольку другие клиенты могли бы начать использовать код, учитывая, что метод является общедоступным. Еще один вариант - сделать функцию защищенной, чтобы в одном и том же пакете в иерархии тестов можно было писать тесты. Однако я бы предпочел написать контрольный пример, сформировав базовый объект один раз, и продолжать изменять мои входные и выходные данные, чем использовать эти обходные пути.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...