Как написать модульное тестирование для Angular/TypeScript для приватных методов с помощью Jasmine

avatar
tymspy
14 марта 2016 в 12:03
154249
12
260

Как вы тестируете приватную функцию в 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;
    }

}

Решение, которое я нашел

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

    Позже удалите тестовый код с помощью инструмента. http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/

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

P.S

  1. Большинство ответов на подобные вопросы не дают решения проблемы, поэтому я задаю этот вопрос

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

Источник
prasanthv
9 мая 2017 в 20:21
0

Что, если частная функция устанавливает общедоступное свойство?

Quaternion
26 мая 2017 в 01:07
27

Мне нравится, что половина ответов должна быть комментариями. ОП задает вопрос, как тебе X? Принятый ответ на самом деле говорит вам, как сделать X. Затем большинство остальных оборачиваются и говорят, что я не только не скажу вам X (что вполне возможно), но вы должны делать Y. Большинство инструментов модульного тестирования (я не здесь речь идет только о JavaScript) способны тестировать приватные функции/методы. Я продолжу объяснять, почему, потому что он, кажется, затерялся в мире JS (очевидно, учитывая половину ответов).

Quaternion
26 мая 2017 в 01:13
20

Хорошей практикой программирования является разбиение проблемы на управляемые задачи, поэтому функция "foo(x:type)" будет вызывать приватные функции a(x:type), b(x:type), c(y:another_type) и d( z:еще_другой_тип). Теперь, поскольку foo управляет вызовами и объединяет вещи, он создает своего рода турбулентность, как обратные стороны камней в ручье, тени, которые действительно сложно проверить на всех диапазонах. Таким образом, легче гарантировать, что каждый подмножество диапазонов допустимо, если вы попытаетесь протестировать только родительский "foo", тестирование диапазона становится очень сложным в случаях.

Quaternion
26 мая 2017 в 01:25
29

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

Quaternion
26 мая 2017 в 01:25
6

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

Flaom
11 марта 2021 в 19:23
1

@Quaternion Этот комментарий к TDD танцует вокруг вопроса OP, фактически не давая какого-либо ценного понимания общей идеи тестирования частных методов. Иногда вам действительно нужно получить доступ к закрытым членам, чтобы иметь хорошее тестовое покрытие, поэтому в тестовом пакете Spring Boot есть утилиты отражения. Несмотря на то, что общедоступные методы обращаются к этим закрытым членам, вполне возможно, что вы не сможете охватить пограничные случаи, если не сможете напрямую вызывать частные методы в своих модульных тестах.

Flaom
11 марта 2021 в 19:56
0

@Quaternion Я вижу! В вашем первоначальном комментарии никто не был отмечен, поэтому я подумал, что вы просто напрямую обращаетесь к OP.

Ответы (12)

avatar
Aaron Beall
14 марта 2016 в 15:24
471

Я с вами, несмотря на то, что цель «только модульное тестирование общедоступного API» является хорошей, бывают случаи, когда это не кажется таким простым, и вы чувствуете, что выбираете между компрометацией API или модуль- тесты. Вы это уже знаете, поскольку это именно то, что вы просите сделать, так что я не буду вдаваться в подробности. :)

В TypeScript я обнаружил несколько способов доступа к закрытым членам для модульного тестирования. Рассмотрим этот класс:

class MyThing {

    private _name:string;
    private _count:number;

    constructor() {
        this.init("Test", 123);
    }

    private init(name:string, count:number){
        this._name = name;
        this._count = count;
    }

    public get name(){ return this._name; }

    public get count(){ return this._count; }

}

Несмотря на то, что TS ограничивает доступ к членам класса, используя private, protected, public, в скомпилированном JS нет закрытых членов, поскольку в JS этого нет. Он используется исключительно для компилятора TS. Для этого:

  1. Вы можете утверждать any и избежать предупреждения компилятором об ограничениях доступа:

    (thing as any)._name = "Unit Test";
    (thing as any)._count = 123;
    (thing as any).init("Unit Test", 123);
    

    Проблема с этим подходом заключается в том, что компилятор просто понятия не имеет, что вы делаете прямо из any, поэтому вы не получаете желаемых ошибок типа:

    (thing as any)._name = 123; // wrong, but no error
    (thing as any)._count = "Unit Test"; // wrong, but no error
    (thing as any).init(0, "123"); // wrong, but no error
    

    Это, очевидно, усложнит рефакторинг.

  2. Вы можете использовать доступ к массиву ([]), чтобы получить доступ к закрытым членам:

    thing["_name"] = "Unit Test";
    thing["_count"] = 123;
    thing["init"]("Unit Test", 123);
    

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

    thing["_name"] = 123; // type error
    thing["_count"] = "Unit Test"; // type error
    thing["init"](0, "123"); // argument error
    

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

Вот рабочий пример в TypeScript Playground.

Изменить для TypeScript 2.6

Другой вариант, который нравится некоторым, заключается в использовании // @ts-ignore (добавлено в TS 2.6), который просто подавляет все ошибки в следующей строке:

// @ts-ignore
thing._name = "Unit Test";

Проблема в том, что он подавляет все ошибки в следующей строке:

// @ts-ignore
thing._name(123).this.should.NOT.beAllowed("but it is") = window / {};

Лично я считаю @ts-ignore кодовым запахом, и, как говорят документы:

мы рекомендуем вам использовать эти комментарии очень экономно. [выделено оригиналом]

d512
7 апреля 2018 в 18:16
77

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

Liam
22 мая 2019 в 08:25
0

Честно говоря, я не знаю, почему это работает это работает, потому что это допустимый JavaScript, а машинописный текст является надмножеством JavaScript. Компилятор типов на самом деле не знает, что вы обращаетесь к членам с ограниченным доступом, и JS не заботится о таких вещах. Таким образом, вы просто обходите TS и переходите непосредственно к реализации JS.

Aaron Beall
22 мая 2019 в 14:21
0

@ Лиам Нет, это не «обход TS», в этом суть. Средство проверки типов распознает свойство и полностью проверяет его тип. Он просто не применяет никаких ограничений доступа. Многие действительные JS вызывают ошибки компиляции TS. Я не уверен, почему в этом случае ограничение доступа игнорируется...

Aaron Beall
22 мая 2019 в 14:48
3

Некоторое «официальное» объяснение поведения (в котором даже упоминается модульное тестирование как вариант использования): github.com/microsoft/TypeScript/issues/19335

Tommaso
10 августа 2019 в 10:00
1

Просто используйте `// @ts-ignore`, как указано ниже. указать линтеру игнорировать закрытый метод доступа

Aaron Beall
25 октября 2019 в 13:28
2

@Tommaso Да, это еще один вариант, но он имеет тот же недостаток, что и использование as any: вы теряете все проверки типов.

nicolas.leblanc
29 октября 2019 в 16:58
2

Лучший ответ, который я когда-либо видел, спасибо @AaronBeall. А также спасибо tymspy за оригинальный вопрос.

Talk is Cheap Show me Code
3 ноября 2020 в 10:21
0

Привет! Один из лучших ответов, которые я до сих пор видел на coderhelper! Примите мою благодарность :)

avatar
brainmonger
4 декабря 2019 в 04:31
12

Это сработало для меня:

Вместо:

sut.myPrivateMethod();

Это:

sut['myPrivateMethod']();
Moff452
6 апреля 2021 в 15:55
0

Да, действительно, это более простой способ, вам не нужно добавлять строку кода!

avatar
Deepu Reghunath
28 ноября 2019 в 17:23
5

вызов приватного метода с использованием квадратных скобок

Ts-файл

class Calculate{
  private total;
  private add(a: number) {
      return a + total;
  }
}

файл spect.ts

it('should return 5 if input 3 and 2', () => {
    component['total'] = 2;
    let result = component['add'](3);
    expect(result).toEqual(5);
});
RGKrish183
2 августа 2020 в 15:31
0

1. Я пробовал ваши решения, при использовании квадратных скобок в узле js нужно использовать импорт или требовать. 2. и мой класс Calculate выглядел как export let cal = new Calculate(); можно получить доступ?

Peter I
14 апреля 2021 в 14:57
0

Это очень хорошее решение, позволяющее сохранить интеллектуальность и протестировать функции.

avatar
Mir-Ismaili
18 мая 2019 в 13:39
49

Вы МОЖЕТЕ вызывать приватные методы!

Если вы столкнулись со следующей ошибкой:

expect(new FooBar(/*...*/).initFooBar()).toEqual(/*...*/)
// TS2341: Property 'initFooBar' is private and only accessible within class 'FooBar'

просто используйте // @ts-ignore:

// @ts-ignore
expect(new FooBar(/*...*/).initFooBar()).toEqual(/*...*/)

Спасибо @Moff452 за его/ее комментарий. Вы также можете написать:

expect(new FooBar(/*...*/)['initFooBar']()).toEqual(/*...*/)
jsnewbie
7 ноября 2019 в 05:53
1

это должно быть наверху!

Aaron Beall
17 января 2020 в 17:50
5

Это, конечно, еще один вариант. Он страдает от той же проблемы, что и as any: вы теряете любую проверку типов, на самом деле вы теряете любую проверку типов для всей строки.

Moff452
6 апреля 2021 в 15:53
1

Для меня принятый ответ лучше, потому что единственное изменение, которое вам нужно написать, это переход с component.callPrivateMetod() на <24779059555633>

avatar
Sani Yusuf
15 ноября 2018 в 13:43
0

Этот маршрут, который я выбираю, — это тот, где я создаю функции вне класса и назначаю функцию своему частному методу.

export class MyClass {
  private _myPrivateFunction = someFunctionThatCanBeTested;
}

function someFunctionThatCanBeTested() {
  //This Is Testable
}

Теперь я не знаю, какой тип правил ООП я нарушаю, но чтобы ответить на вопрос, вот как я тестирую частные методы. Я приветствую любого, кто посоветует плюсы и минусы этого.

avatar
Devpool
30 августа 2018 в 14:26
0

Ответ Аарона лучший и работает на меня :) Я бы проголосовал, но, к сожалению, не могу (отсутствует репутация).

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

Например:

class Something {
  save(){
    const data = this.getAllUserData()
    if (this.validate(data))
      this.sendRequest(data)
  }
  private getAllUserData () {...}
  private validate(data) {...}
  private sendRequest(data) {...}
}

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

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

avatar
CTS_AE
26 июня 2018 в 22:48
4

Как уже отмечали многие, как бы вы ни хотели протестировать приватные методы, вам не следует взламывать свой код или транспилятор, чтобы они работали на вас. Современный TypeScript будет отрицать большинство хаков, которые люди предлагали до сих пор.


Решение

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

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

Пример

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

https://patrickdesjardins.com/blog/how-to-unit-test-private-method-in-typescript-part-2

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

До
class User{
    public getUserInformationToDisplay(){
        //...
        this.getUserAddress();
        //...
    }

    private getUserAddress(){
        //...
        this.formatStreet();
        //...
    }
    private formatStreet(){
        //...
    }
}
После
class User{
    private address:Address;
    public getUserInformationToDisplay(){
        //...
        address.getUserAddress();
        //...
    }
}
class Address{
    private format: StreetFormatter;
    public format(){
        //...
        format.ToString();
        //...
    }
}
class StreetFormatter{
    public toString(){
        // ...
    }
}
avatar
Ryan Hansen
22 декабря 2017 в 06:08
6

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

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

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

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

Мы не смогли сделать это здесь, разрешив объекту FooBar принимать элемент Bar, который не был готов на момент создания FooBar, и компенсировали это своего рода «взломом» объекта FooBar, чтобы принять во внимание ситуацию. своими руками.

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

В вашем примере свойство "status" панели не похоже на допустимое состояние, в котором FooBar может его принять, поэтому FooBar что-то делает с ним, чтобы исправить эту проблему.

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

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

avatar
Leon Adler
1 июля 2016 в 09:28
4

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

Если у вас есть общедоступный API с 5 методами, любой потребитель вашего класса может их использовать, поэтому вам следует протестировать их. Потребитель не должен получать доступ к закрытым методам/свойствам вашего класса, то есть вы можете изменять закрытые члены, когда общедоступные функции остаются прежними.


Если вы полагаетесь на внутреннюю расширяемую функциональность, используйте protected вместо private.
Обратите внимание, что protected по-прежнему является публичным API (!), просто используется по-другому.

class OverlyComplicatedCalculator {
    public add(...numbers: number[]): number {
        return this.calculate((a, b) => a + b, numbers);
    }
    // can't be used or tested via ".calculate()", but it is still part of your public API!
    protected calculate(operation, operands) {
        let result = operands[0];
        for (let i = 1; i < operands.length; operands++) {
            result = operation(result, operands[i]);
        }
        return result;
    }
}

Защищенные свойства в модульном тестировании так же, как их использует потребитель, путем создания подклассов:

it('should be extensible via calculate()', () => {
    class TestCalculator extends OverlyComplicatedCalculator {
        public testWithArrays(array: any[]): any[] {
            const concat = (a, b) => [].concat(a, b);
            // tests the protected method
            return this.calculate(concat, array);
        }
    }
    let testCalc = new TestCalculator();
    let result = testCalc.testWithArrays([1, 'two', 3]);
    expect(result).toEqual([1, 'two', 3]);
});
avatar
tymspy
18 марта 2016 в 06:54
20

Поскольку большинство разработчиков не рекомендуют тестировать приватную функцию, почему бы не протестировать ее?

Например,

ВашКласс.ts

export class FooBar {
  private _status: number;

  constructor( private foo : Bar ) {
    this.initFooBar({});
  }

  private initFooBar(data){
    this.foo.bar( data );
    this._status = this.foo.foo();
  }
}

TestYourClass.spec.ts

describe("Testing foo bar for status being set", function() {

...

//Variable with type any
let fooBar;

fooBar = new FooBar();

...
//Method 1
//Now this will be visible
fooBar.initFooBar();

//Method 2
//This doesn't require variable with any type
fooBar['initFooBar'](); 
...
}

Спасибо @Aaron, @Thierry Templier.

sridesmet
20 августа 2018 в 06:47
2

Я думаю, что typescript выдает ошибки linting, когда вы пытаетесь вызвать закрытый/защищенный метод.

tymspy
21 августа 2018 в 06:28
2

@Gudgip выдаст ошибки типа и не скомпилируется. :)

vaibhavcool20
17 декабря 2020 в 17:47
0

Мне нужна помощь в отношении параметризации теста interface Part { partNumber: string; }, который выглядит так: unpickPart(index: number, part: Part): void { //do stuff } нужно каким-то образом вызвать часть unpick.

avatar
Martin
14 марта 2016 в 13:30
11

Не пишите тесты для приватных методов. Это побеждает смысл модульных тестов.

  • Вы должны протестировать общедоступный API вашего класса
  • Нельзя тестировать детали реализации вашего класса

Пример

class SomeClass {

  public addNumber(a: number, b: number) {
      return a + b;
  }
}

Тест для этого метода не должен изменяться, если позже изменится реализация, но behaviour общедоступного API останется прежним.

class SomeClass {

  public addNumber(a: number, b: number) {
      return this.add(a, b);
  }

  private add(a: number, b: number) {
       return a + b;
  }
}

Не делайте общедоступными методы и свойства только для того, чтобы их протестировать. Обычно это означает, что либо:

  1. Вы пытаетесь протестировать реализацию, а не API (общедоступный интерфейс).
  2. Вы должны переместить рассматриваемую логику в отдельный класс, чтобы упростить тестирование.
Martin
4 ноября 2016 в 08:19
5

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

Galdor
11 мая 2017 в 08:18
1

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

Martin
11 мая 2017 в 09:26
2

@ user3725805 это пример тестирования реализации, а не поведения. Лучше изолировать, откуда берется приватный номер: константа, конфиг, конструктор -- и оттуда тестировать. Если частное не приходит из какого-то другого источника, то оно попадает в антипаттерн «магическое число».

Galdor
12 мая 2017 в 10:03
3

И почему не разрешено тестировать реализацию? Модульные тесты хороши для обнаружения неожиданных изменений. Когда по какой-то причине конструктор забывает установить число, тест сразу же завершается с ошибкой и предупреждает меня. Когда кто-то меняет реализацию, тест тоже дает сбой, но я предпочитаю использовать один тест, чем иметь необнаруженную ошибку.

Syed Aqeel Ashiq
7 ноября 2017 в 08:45
2

+1. Отличный ответ. @TimJames Рассказ о правильной практике или указание на ошибочный подход - это сама цель SO. Вместо того, чтобы найти хакерский хрупкий способ добиться всего, чего хочет ОП.

d512
7 апреля 2018 в 18:21
2

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

Jon Rimmer
22 февраля 2019 в 17:04
4

Если неприемлемо делать приватный метод общедоступным только для того, чтобы его можно было протестировать, почему можно переместить метод в отдельный класс!? Обе ситуации связаны с потребностями тестирования, управляющими структурой реализации, за исключением того, что последняя еще более агрессивна: у вас есть целый класс, единственная цель существования которого — позволить вам что-то протестировать.

avatar
Thierry Templier
14 марта 2016 в 13:19
2

Я согласен с @toskv: я бы не рекомендовал этого делать :-)

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

Например:

export class FooBar {
  private _status: number;

  constructor( private foo : Bar ) {
    this.initFooBar({});
  }

  private initFooBar(data){
    this.foo.bar( data );
    this._status = this.foo.foo();
  }
}

будет преобразовано в:

(function(System) {(function(__moduleName){System.register([], function(exports_1, context_1) {
  "use strict";
  var __moduleName = context_1 && context_1.id;
  var FooBar;
  return {
    setters:[],
    execute: function() {
      FooBar = (function () {
        function FooBar(foo) {
          this.foo = foo;
          this.initFooBar({});
        }
        FooBar.prototype.initFooBar = function (data) {
          this.foo.bar(data);
          this._status = this.foo.foo();
        };
        return FooBar;
      }());
      exports_1("FooBar", FooBar);
    }
  }
})(System);

См. этот plunkr: https://plnkr.co/edit/calJCF?p=preview.