2016-12-20 8 views
7

コンポーネントの単体テストを角度1.5で記述しようとしています。私はそのコンポーネントとそのdomノードをユニットテストしたい。このコンポーネントには、かなり複雑な子コンポーネントが含まれています。子コンポーネントを無視して角度1.5ユニットテストコンポーネント

私の目標は、子コンポーネントをコンパイルせずに外部コンポーネントをユニットテストすることです。

DOMもテストしたいので、このテストでは$ componentControllerを使用するだけでは不十分です。ここで

は私が達成したいものの短い例です:

コンポーネントコード:私の成分のための

angular.module('app').component('myComponent', { 
    bindings: { 
    username: '<', 
    }, 
    template: ` 
    <span>{{ $ctrl.username }}</span> 
    <my-complex-component /> 
    ` 
    controller: function() {} 
}); 

ユニットテスト:

it('my-component should render username', function() { 
    var template = '<my-component username="username"></my-component>', 
    element, 
    scope, 
    date; 

    scope = $rootScope.$new(); 
    scope.username = 'John'; 

    element = $compile(template)(scope); 
    scope.$digest(); 

    username = element.find('span'); 
    expect(username.text()).to.be.equal('John'); 
}); 

私のコンプレックス成分インスタンス化するべきではありません。それはそのままテンプレートに抵抗するはずです。ユニットテストの要素を作成すると、

<span>John</span> 
<my-complex-component /> 

になる必要がありますこれを行う方法はありますか?

+0

私が知っているように、それは期待どおりに動作します。コンポーネントをコンパイルすると、内部コンポーネントはコンパイルされません。単に 'console.log(element)'を見てください。 –

+0

残念ながら、my-componentとmy-complex-componentはどちらもモジュールアプリにあります。モジュールをモックするためにangular.mock.module( 'app')を呼び出さなければならないので、両方のコンポーネントをロードし、my-complex-componentもコンパイルしようとします。 –

+0

あなたは 'my-complex-component'をモックしようとすることができます。 mockingに関する[この回答](http://stackoverflow.com/questions/17533052/how-do-you-mock-directives-to-enable-unit-testing-of-higher-level-directive#answer-21923462)を参照してください。代わりに[$ compileProvider.component](https://docs.angularjs.org/api/ng/provider/$compileProvider#component)を使用してください – user2718281

答えて

1

あり、それをテストする方法があるが、最終的な結果は次のようになります。

<span>John</span> 
<ng-transclude></ng-transclude> 

コンポーネントコード:

angular.module('app').component('myComponent', { 
    enter code herebindings: { 
    username: '<', 
    }, 
    template: ` 
    <span>{{ $ctrl.username }}</span> 
    <ng-transclude></ng-transclude> 
    `, 
    transclude: true, // Added property 
    controller: function() {} 
}); 

あなたは私が<my-complex-component>を削除し、代わりに<ng-transclude>を追加見ることができるように。

これは、外部から情報を追加することができ、ng-transcludeの位置に注入されることを意味します。例えば

これはあなたのメインのhtmlで:

<my-component> 
    <my-complex-component></my-complex-component> 
</my-component> 

は、あなたが最初から望んでいたように、DOMになります:

<span>John</span> 
<my-complex-component></my-complex-component> 

テストが動作するはずその後。

私はこの回答があなたの望むものであり、それがあなたに役立つことを願っています。

+1

コンポーネントのマークアップを変更することが正しいかどうかはわかりません。マークアップはあまり直感的ではありません。また、複数の子コンポーネントがある場合はどうなりますか? – isherwood

+0

あなたのコンポーネントをよりテスト可能にしたい場合、テストを中断することなく、メインのコンポーネントの中に多くのコンポーネントを配置することができます。このようにして、あなたの主なコンポーネントがまだ動作している(または動作していない)ことが分かります。 – Alon

2

Here is a very good explanation現在のコンポーネントの下にツリー全体をレンダリングせずにコンポーネントをテストする方法です。何をしたい

は(子コンポーネントの全体のテンプレートをレンダリング避ける)

と角1.5は、アウト・オブ・ボックスにそれを提供していません

浅いレンダリングと呼ばれています。

上記のリンクを参照すると、Wojciech Zawistowskiは浅いレンダリングを実現するために下のヘルパーを使用する方法を示します。

export function componentSpyOn(name) { 
    function componentSpy($provide) { 
    componentSpy.bindings = []; 

    $provide.decorator(name + 'Directive', ($delegate) => { 
     let component = $delegate[0]; 

     component.template = ''; 
     component.controller = class { 
     constructor() { 
      componentSpy.bindings.push(this); 
     } 
     }; 

     return $delegate; 
    }); 
    } 

    return componentSpy; 
} 
0

単体テストの子コンポーネントのモジュール定義を空のモジュールで上書きできます。

// Unit Test Parent component 
describe('Unit Testing: myComponent Component',() => { 

    beforeEach(() => { 
    // overwrite module 
    angular.module('myComplexComponent', []); 
    module('myComponent'); 
    }); 
}); 

は今親コンポーネントは、まだ注入し、子コンポーネントをレンダリングしようとするだろうが、この子コンポーネントが完全であるように空何も起こりません。

関連する問題