2016-12-20 3 views
7

Ich versuche, einen Komponententest für eine Komponente in Angular 1,5 zu schreiben. Ich möchte diese Komponente und ihre Dom-Knoten testen. Diese Komponente enthält eine untergeordnete Komponente, die ziemlich komplex ist.Angular 1.5 Unit-Tests Komponente während Kind Komponenten ignorieren

Mein Ziel ist es, Unit-Test die äußere Komponente, ohne die untergeordnete Komponente zu kompilieren.

Da ich das DOM als auch testen will, ist es nicht ausreichend $ Component für diesen Test zu verwenden.

Hier ist ein kleines Beispiel von dem, was Ich mag erreichen würde:

Komponentencode:

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

Unit-Test für my-Komponente:

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'); 
}); 

my-Komplex-Komponente sollte nicht instanziiert werden. Es sollte in der Vorlage wie es ist widerstehen. Das Erstellen des Elements im Komponententest sollte zu

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

führen Gibt es eine Möglichkeit, dies zu tun?

+0

Wie ich weiß, funktioniert es genau so, wie Sie es erwartet haben. Wenn Sie Ihre Komponente kompilieren, werden keine inneren Komponenten kompiliert. Schauen Sie sich einfach 'console.log (element)' an. –

+0

Leider befinden sich my-component und my-complex-component beide in der Modul-App. Da ich angle.mock.module ('app') aufrufen muss, um das Modul zu verspotten, lädt es beide Komponenten und versucht auch, meine-complex-Komponente zu kompilieren. –

+0

können Sie versuchen, "My-Complex-Komponente" zu verspotten. Siehe [diese Antwort] (http://stackoverflow.com/questions/17533052/how-do-you-mock-directives-to-enable-unit-testing-of-higher-level-directive#answer-21923462) auf Mocking eine Direktive, aber benutze [$ compileProvider.component] (https://docs.angularjs.org/api/ng/provider/$compileProvider#component) statt – user2718281

Antwort

1

Es gibt einen Weg, es zu testen, aber das Endergebnis wird sein:

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

Komponentencode:

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

Wie Sie mich <my-complex-component> gelöscht sehen können, und hinzugefügt <ng-transclude> statt.

Dies bedeutet, dass Sie Ihre Informationen von außen hinzufügen können und es wird an der Stelle der ng-Transclude injiziert werden.

Zum Beispiel dieser in der Haupt html:

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

Wird in der DOM in der Art und Weise, dass Sie von Anfang an wollte:

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

Danach Ihre Test funktionieren sollte.

Ich hoffe, dass diese Antwort ist, was Sie wollten und dass es Ihnen helfen wird.

+1

Ich bin mir nicht sicher, ob ich das Markup der Komponente hier ändern kann. Es macht das Markup weniger intuitiv. Was passiert auch, wenn mehr als eine Kindkomponente vorhanden ist? – isherwood

+0

Ich denke, es ist ein besserer Ansatz, wenn Sie möchten, dass Ihre Komponenten besser testbar sind, und auf diese Weise können Sie so viele Komponenten in Ihre Hauptkomponente einfügen, ohne Ihre Tests zu unterbrechen. Auf diese Weise können Sie sehen, dass Ihre Hauptkomponente immer noch funktioniert (oder nicht), wenn die Dinge zu brechen beginnen. – Alon

2

Here is a very good explanation wie eine Komponente zu testen, ohne den gesamten Baum unter der aktuellen Komponente zu rendern.

Was Sie wollen, ist

flache Rendering (vermeiden Sie die ganze Vorlage des Kindes Komponente Rendering) genannt

und Angular 1.5 bietet nicht es out-of-the-box.

Wenn Sie sich den obigen Link ansehen, zeigt Wojciech Zawistowski, wie Sie den folgenden Helfer verwenden, um ein flaches Rendering zu erreichen.

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

Sie könnten einfach die untergeordnete Komponentenmoduldefinition im Komponententest mit einem leeren Modul überschreiben.

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

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

Jetzt würde die übergeordnete Komponente nach wie vor versuchen, die untergeordnete Komponente zu injizieren und machen, aber wie dieses Kind Komponente völlig leer nichts passiert ist.

Verwandte Themen