Как вы тестируете приватную функцию в angular 2?
class FooBar {
private _status: number;
constructor( private foo : Bar ) {
this.initFooBar();
}
private initFooBar(){
this.foo.bar( "data" );
this._status = this.fooo.foo();
}
public get status(){
return this._status;
}
}
Решение, которое я нашел
Поместите сам тестовый код в замыкание или добавьте код внутри замыкания, в котором хранятся ссылки на локальные переменные существующих объектов во внешней области видимости.
Позже вычеркните тестовый код с помощью инструмента. http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/
Пожалуйста, предложите мне лучший способ решить эту проблему, если вы сделали что-нибудь?
PS
Большая часть ответа на вопрос такого же типа, как этот, не дает решения проблемы, поэтому я задаю этот вопрос
Большинство разработчиков говорят, что вы не тестируете частные функции, но я не говорю, что они неправильные или правильные, но в моем случае есть необходимость тестировать частные.
источник
Ответы:
Я с вами, хотя хорошей целью является «только модульное тестирование общедоступного API», бывают случаи, когда это не кажется таким простым, и вы чувствуете, что выбираете между компрометацией API или модульных тестов. Вы уже знаете это, поскольку именно это вы и просите, поэтому я не буду вдаваться в подробности. :)
В TypeScript я обнаружил несколько способов получить доступ к закрытым членам ради модульного тестирования. Рассмотрим этот класс:
Несмотря на то, TS ограничивает доступ к членам класса с использованием
private
,protected
,public
, скомпилированный JS не имеет частных пользователей, так как это не вещь в JS. Он используется исключительно для компилятора TS. Therefor:Вы можете утверждать
any
и избегать компилятора, предупреждая вас об ограничениях доступа:Проблема этого подхода заключается в том, что компилятор просто не имеет представления о том, что вы делаете правильно
any
, поэтому вы не получите желаемых ошибок типа:Это, очевидно, усложнит рефакторинг.
Вы можете использовать массив access (
[]
), чтобы получить доступ к закрытым членам:Несмотря на то, что это выглядит странно, TSC фактически проверит типы, как если бы вы обращались к ним напрямую:
Если честно, я не знаю, почему это работает.Это очевидно преднамеренный «аварийный люк», чтобы дать вам доступ к частным пользователям без потери безопасности типа. Это именно то, что я думаю, вы хотите для вашего юнит-тестирования.Вот рабочий пример в TypeScript Playground .
Редактировать для TypeScript 2.6
Другим вариантом, который некоторым нравится, является использование
// @ts-ignore
( добавлено в TS 2.6 ), которое просто подавляет все ошибки в следующей строке:Проблема в том, что она подавляет все ошибки в следующей строке:
Я лично рассматриваю
@ts-ignore
кодовый запах и, как говорят доктора:источник
as any
: вы теряете все проверки типов.Вы можете вызывать частные методы . Если вы столкнулись со следующей ошибкой:
просто используйте
// @ts-ignore
:источник
as any
что и то, что вы теряете любую проверку типов, фактически вы теряете любую проверку типов во всей строке.Поскольку большинство разработчиков не рекомендует тестировать закрытые функции , почему бы не протестировать их?
Например.
YourClass.ts
TestYourClass.spec.ts
Спасибо @Aaron, @Thierry Templier.
источник
Не пишите тесты для частных методов. Это побеждает точку юнит-тестов.
пример
Тест для этого метода не должен изменяться, если впоследствии реализация изменится, но
behaviour
открытый API останется прежним.Не делайте методы и свойства общедоступными только для того, чтобы их протестировать. Обычно это означает, что либо:
источник
Смысл «не тестировать приватные методы» на самом деле заключается в тестировании класса как того, кто его использует .
Если у вас есть общедоступный API с 5 методами, любой потребитель вашего класса может использовать их, и поэтому вы должны их протестировать. Потребитель не должен получать доступ к закрытым методам / свойствам вашего класса, а это значит, что вы можете изменять закрытые члены, когда открытая функциональность остается неизменной.
Если вы полагаетесь на внутреннюю расширяемую функциональность, используйте
protected
вместоprivate
.Обратите внимание, что
protected
это все еще публичный API (!) , Только используемый по-другому.Модульное тестирование защищенных свойств аналогично тому, как потребитель будет использовать их, используя подклассы:
источник
Это сработало для меня:
Вместо того:
Это:
источник
Извините за некро в этом посте, но я чувствую себя обязанным взвесить пару вещей, которые, кажется, не были затронуты.
Прежде всего - когда во время модульного тестирования нам нужен доступ к закрытым членам класса, это, как правило, большой, толстый красный флаг, который мы обманываем в нашем стратегическом или тактическом подходе и непреднамеренно нарушаем принцип единственной ответственности, подталкивая поведение там, где оно не принадлежит. Чувство необходимости доступа к методам, которые на самом деле являются не чем иным, как изолированной подпрограммой процедуры построения, является одним из наиболее распространенных случаев этого; тем не менее, это похоже на то, что ваш начальник ожидает, что вы явитесь на работу, готовый к работе, а также имеет некоторую извращенную потребность знать, через какую утреннюю рутину вы прошли, чтобы привести вас в это состояние ...
Другой наиболее распространенный случай этого происходит, когда вы пытаетесь проверить общеизвестный «класс бога». Это особая проблема сама по себе, но она страдает от той же самой основной проблемы, связанной с необходимостью знать интимные детали процедуры - но это выходит за рамки темы.
В этом конкретном примере мы фактически возложили ответственность за полную инициализацию объекта Bar конструктору класса FooBar. В объектно-ориентированном программировании одним из основных принципов является то, что конструктор является «священным» и должен быть защищен от недопустимых данных, которые могут сделать недействительным его собственное внутреннее состояние и оставить его готовым к сбою где-то еще вниз по течению (в том, что может быть очень глубоким). трубопровод.)
Мы не смогли сделать это здесь, позволив объекту FooBar принять Bar, который не был готов в момент создания FooBar, и компенсировали своего рода «взломом» объекта FooBar, чтобы все стало по-своему. Руки.
Это является результатом отказа придерживаться другого принципа объектно-ориентированного программирования (в случае Bar), который заключается в том, что состояние объекта должно быть полностью инициализировано и готово обрабатывать любые входящие вызовы его «открытых членов» сразу после создания. Теперь это не означает, что сразу после вызова конструктора во всех случаях. Когда у вас есть объект, который имеет много сложных сценариев построения, тогда лучше выставить сеттеры для его необязательных членов для объекта, который реализован в соответствии с шаблоном создания проекта (Factory, Builder и т. Д.) В любом из последние случаи,
В вашем примере свойство Bar «status», по-видимому, не находится в допустимом состоянии, в котором FooBar может его принять - поэтому FooBar что-то с ним делает, чтобы исправить эту проблему.
Вторая проблема, которую я вижу, заключается в том, что, похоже, вы пытаетесь протестировать свой код, а не практиковаться в разработке через тестирование. Это определенно мое собственное мнение на данный момент; но этот тип тестирования действительно является анти-паттерном. В конечном итоге вы попадаете в ловушку осознания того, что у вас есть основные проблемы проектирования, которые мешают тестированию вашего кода после факта, а не пишут необходимые вам тесты и впоследствии программируют для тестов. В любом случае, если вы решите проблему, вы все равно должны получить такое же количество тестов и строк кода, если бы вы действительно достигли реализации SOLID. Итак - зачем пытаться перепроектировать свой путь в тестируемый код, если вы можете просто решить этот вопрос в начале ваших усилий по разработке?
Если бы вы сделали это, то вы бы поняли гораздо раньше, что вам придется написать какой-то довольно странный код, чтобы протестировать ваш дизайн, и у вас была бы возможность на раннем этапе перестроить ваш подход, переключив поведение на реализации, которые легко проверяемы
источник
Я согласен с @toskv: я бы не рекомендовал это делать :-)
Но если вы действительно хотите протестировать свой закрытый метод, вы можете знать, что соответствующий код для TypeScript соответствует методу прототипа функции конструктора. Это означает, что его можно использовать во время выполнения (тогда как у вас, вероятно, будут некоторые ошибки компиляции).
Например:
будет перенесено в:
Смотрите этот план: https://plnkr.co/edit/calJCF?p=preview .
источник
Как уже говорили многие, если вы хотите протестировать приватные методы, вы не должны взламывать свой код или транспортер, чтобы он работал на вас. Современный TypeScript будет отрицать большинство всех взломов, которые люди предоставили до сих пор.
Решение
TLDR ; если метод должен быть протестирован, то вы должны отделить код от класса, чтобы вы могли предоставить метод для публичного тестирования.
Причина, по которой у вас есть метод private, заключается в том, что функциональность не обязательно должна быть доступна для этого класса, и поэтому, если функциональность там не принадлежит, ее следует разделить на собственный класс.
пример
Я наткнулся на эту статью, которая объясняет, как вам следует тестировать частные методы. Здесь даже рассматриваются некоторые из методов и почему они являются плохими реализациями.
https://patrickdesjardins.com/blog/how-to-unit-test-private-method-in-typescript-part-2
Примечание . Этот код взят из блога, на который есть ссылки выше (я дублирую на случай, если содержание ссылки меняется)
Перед Послеисточник
вызовите закрытый метод, используя квадратные скобки
Ts файл
файл spect.ts
источник
Ответ Аарона самый лучший и работает на меня :) Я бы проголосовал, но, к сожалению, не могу (отсутствует репутация).
Я должен сказать, что тестирование частных методов - это единственный способ использовать их и иметь чистый код с другой стороны.
Например:
Имеет смысл не тестировать все эти методы сразу, потому что нам нужно было бы смоделировать те частные методы, которые мы не можем отыграть, потому что не можем получить к ним доступ. Это означает, что нам нужно много конфигурации для модульного теста, чтобы проверить это в целом.
При этом лучший способ проверить описанный выше метод со всеми зависимостями - это сквозное тестирование, поскольку здесь необходим интеграционный тест, но тест E2E не поможет вам, если вы практикуете TDD (Test Driven Development), но тестируете любой метод будет.
источник
Я выбрал этот маршрут, где я создаю функции вне класса и назначаю функцию моему приватному методу.
Теперь я не знаю, какой тип правил ООП я нарушаю, но, чтобы ответить на вопрос, я проверяю частные методы. Я приветствую любого, кто посоветует за и против этого.
источник