No more 💩 angular unit test / #1 Component template
Tags: angular, typescript, testing
Published: 2019-11-14 16:38:26

⚠️ Use `ng-mocks` in your unit tests
_More details_ after about this lib. Just keep in mind that __it's awesome__.

### Standard first
I love use standard. Angular makes the choice to use __Karma/Jasmine__, so I continue to use it.

> 😇 YES, __Jest__ is also a great challenger and a __powerful tool to write and execute your unit tests__

### Testing your components
There are two things to test with your components.

* Template (.html)
* Logic (.ts).


#### Testing template
What can be tested and needed to be tested ?

* All Angular directive `*ngIf`, `*ngFor`, ...
* All inputs `@Input()`
* All outputs `@Output()`

> __🤔 Why we need to test `*ngIf` for example ?__
>
> Image in your commit #1 you add `*ngIf` in your template without tests. Someone commit the #2 and erase by accident the conditional directive. __No test cover this regression__.

🔥 Use `MockRender` from `ng-mocks` to create your component fixture.

```typescript
import { TestBed } from '@angular/core/testing';
import { YourComponent } from './your-component.component.ts';
import { MockRender } from 'ng-mocks';

describe('YourComponent', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [YourComponent]
    });
  });

  it('should create', () => {
    const fixture = MockRender(`<your-component></your-component>`);
    expect(fixture.componentInstance).toBeTruthy();
  });

  it('should display description', () => {
    const fixture = MockRender(
      `<your-component [description]="description"></your-component>`,
      { description: 'hello world' }
    );
    fixture.detectChanges();

    const descriptionEl = fixture.debugElement.query(By.css('.description');
    expect(descriptionEl.nativeElement.innerHTML).toEqual('hello world');
  });
});
```

🚀 To improve _performance_ and _to scope_ your unit test, use `MockComponent` from `ng-mocks`

With this method, child components become __black box__.

```typescript
import { TestBed } from '@angular/core/testing';
import { YourComponent } from './your-component.component.ts';
import { YourChildComponent } from './your-child-component.component.ts';
import { MockRender, MockComponent } from 'ng-mocks';

describe('YourComponent', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [YourComponent, MockComponent(YourChildComponent)]
    });
  });

  it('should trigger data', () => {
    let receivedData = null;
    const fixture = MockRender(
        `<my-component (getData)="getData($event)></my-component>`,
        { getData: data => receivedData = data; }
    );
    fixture.detectChanges();

    const triggerDataEl = fixture.debugElement.query(By.css('.trigger-data'));
    const childComponent: YourChildComponent = triggerDataEl.componentInstance;
    childComponent.triggerData.emit('hello world');
    fixture.detectChanges();

    expect(receivedData).toEqual('hello world');
  });
});
```

In this example, we trigger the output from the child component. And get an output from our component.

#### Testing logic

__In the next post.__

I hope this article can helps you in your development. 🐼