2010-10-06 3 views
3

У меня есть набор классов, которые имеют зависимости во время создания экземпляра, то есть при создании объекта типа A он также создает другой тип B, который впоследствии создает другие типы C и т. Д.Конструкторы подделки для модульных тестов

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

Итак, есть ли способ «черной магии» взломать загрузчик Java-классов, чтобы вместо этого создавать классы поддельного тестирования вместо обычных при создании объектов с помощью new?

Спасибо!

ответ

6

Почему бы не добавить конструктор, который занимает этих зависимостей в качестве параметров, вместо того, чтобы создавать их самостоятельно в конструкторе? Лично я бы добавил это и удалил другой. Вводя зависимости, этот код легче тестировать и более гибко в будущем (так как вы можете легко добавить другую реализацию позже, без изменения кода.)

+0

Это не то, о чем я просил (потому что я уже знал, что, поскольку это может быть прочитано в вопросе), я хочу знать, могу ли я как-то обойти загрузчик классов: -/ – fortran

+0

@fortran: Где в вопрос признает, что ваш конструктор в основном делает слишком много? Если есть * способы сделать это, они будут очень уродливыми. Почему вы не вводите свои варианты простым, обычным способом? –

+0

, потому что я слишком ленив: -p – fortran

2

Что вы хотите - использовать макет классов. Подумайте о том, как использовать любую инфраструктуру для этого. Вот хороший - https://jmockit.dev.java.net/

+0

Или JMock или одна из многих насмешливых библиотек. Вы даже можете использовать Proxy.newProxy() напрямую, что большинство из них используют. –

2

Вы можете достичь предполагаемого поведения без изменения исходных источников путем изменения пути к классам. Создайте фиктивные классы во второй исходной папке с одинаковыми именами и пакетами. Затем поместите фиктивные классы в classpath и удалите реальные.

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

1

JMockit соответствует требованиям идеально. Например, вы могли бы написать тест, как это:

// In production code: 
public final class ClassUnderTest 
{ 
    private final SomeDependency dep; 

    public ClassUnderTest(String someData) 
    { 
     dep = new SomeDependency(someData); 
    } 

    void methodToBeTested() { ... int i = dep.doSomething("xpto", true); ... } 
} 

final class SomeDependency 
{ 
    int doSomething(String s, boolean b) { ... } 
} 

// In test code: 
public final class MyTest 
{ 
    @Test 
    public void mockingInternalDependencies() 
    { 
     new Expectations() 
     { 
      SomeDependency mockedDep; 

      { 
       mockedDep.doSomething(anyString, anyBoolean); result = 123; 
      } 
     }; 

     new ClassUnderTest("blah blah").methodToBeTested(); 
    } 
} 
0

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