Как смоделировать строительство объекта? - PullRequest
6 голосов
/ 18 сентября 2008

Есть ли способ смоделировать конструкцию объекта, используя JMock в Java?

Например, если у меня есть такой метод:

public Object createObject(String objectType) {
    if(objectType.equals("Integer") {
        return new Integer();
    } else if (objectType.equals("String") {
        return new String();
    }
}

... есть ли способ смоделировать ожидание конструкции объекта в тестовом методе?

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

Так что вместо:

assertTrue(a.createObject() instanceof Integer);

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

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


Для получения дополнительной информации:

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

Возможно, ближе к тому, что я на самом деле ищу, это: есть ли способ смоделировать весь класс (используя CGLib) одним махом, без указания каждого метода для заглушения?

То есть макет оборачивается в конструкторе, поэтому очевидно, что к нему можно вызывать методы, способен ли JMock динамически выводить из строя каждый метод?

Я думаю, нет, так как это было бы довольно сложно. Но знать, что я лаю не на том дереве, тоже ценно: -)

Ответы [ 6 ]

6 голосов
/ 18 сентября 2008

Единственное, о чем я могу думать, - это иметь метод create на фабричном объекте, который вы бы, чем высмеивали.

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

4 голосов
/ 18 сентября 2008

jmockit может сделать это.

Смотрите мой ответ в https://stackoverflow.com/questions/22697#93675

1 голос
/ 18 сентября 2008

Увы, я думаю, что виноват в том, что задал не тот вопрос.

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

public Wrapper wrapObject(Object toWrap) {
    if(toWrap instanceof ClassA) {
        return new Wrapper((ClassA) toWrap);
    } else if (toWrap instanceof ClassB) {
        return new Wrapper((ClassB) toWrap);
    } // etc

    else {
        return null;
    }
}

Я задавал вопрос, как узнать, был ли вызван метод "new ClassAWrapper ()", потому что трудно получить объект toWrap в изолированном тесте. И обертка (если ее даже можно так назвать) выглядит довольно странно, поскольку она использует один и тот же класс для обертывания разных объектов, просто использует разные конструкторы [1]. Я подозреваю, что если бы я задал вопрос немного лучше, я бы быстро получил ответ:

"Вы должны смоделировать Object toWrap, чтобы сопоставить экземпляры, для которых вы тестируете, в различных методах тестирования, и осмотреть получившийся объект Wrapper, чтобы найти возвращаемый правильный тип ... и надеяться, что вам повезло, что вы не не надо издеваться над миром, чтобы создавать разные экземпляры ;-) "

Теперь у меня есть правильное решение проблемы, спасибо!

[1] открытие вопроса о том, следует ли это реорганизовать, выходит за рамки моей нынешней проблемы: -)

0 голосов
/ 18 сентября 2008

Внедрение зависимостей или инверсия управления.

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

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

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

0 голосов
/ 18 сентября 2008

Вы знакомы с Внедрением зависимости ?

Если нет, то вам, несомненно, будет полезно узнать об этой концепции. Я думаю, что старый добрый Inversion of Control Containers и паттерн Dependency Injection от Martin Fowler послужат хорошим введением.

При использовании Dependency Injection (DI) у вас будет объект-контейнер DI, способный создавать для вас все виды классов. Тогда ваш объект будет использовать контейнер DI для создания экземпляров классов, и вы будете смеяться над контейнером DI, чтобы проверить, что класс создает экземпляры ожидаемых классов.

0 голосов
/ 18 сентября 2008

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

Что-то не так в вашем подходе к тестированию здесь. Любая причина, почему вам нужно проверить, что явные конструкторы вызываются?
Утверждение типа возвращаемого объекта кажется нормальным для тестирования реализаций фабрики. Относитесь к createObject как к черному ящику. Изучите, что он возвращает, но не управляйте, как он это делает. Никому это не нравится:

Обновление об обновлении: Ой! Отчаянные меры для отчаянных времен, а? Я был бы удивлен, если JMock позволяет это ... как я сказал, это работает на интерфейсах .. не конкретных типах. Итак

  • Либо попытайтесь потратить некоторое усилие на то, чтобы сделать эти надоедливые входные объекты "инстанцируемыми" под тестовым набором. Подойдите к своему подходу снизу вверх.
  • Если это невозможно, вручную протестируйте его с точками останова (я знаю, что это отстой). Затем добавьте комментарий «Коснитесь на свой страх и риск» в видимой зоне исходного файла и продолжайте. Борись в другой день.
...