Home  >  Article  >  Web Front-end  >  4 tips for writing Angular unit tests, come and take a look!

4 tips for writing Angular unit tests, come and take a look!

青灯夜游
青灯夜游forward
2022-08-11 20:22:492231browse

AngularHow to perform unit testing? In this article, I will share with you 4 high-level techniques for writing Angular unit tests. I hope it will be helpful to you!

4 tips for writing Angular unit tests, come and take a look!

Testing ideas:

  • 1. If you can unit test, try to give priority to unit testing
  • 2 .Cannot be unit tested. Testing is carried out by encapsulating a layer, such as encapsulating the test into a component, but it is weaker than integration testing
  • 3.Integration testing
  • 4.E2E testing

The difficulty of the test gradually increases, and the more time it takes. If you want to make testing simple, then during development, you should consciously clarify your ideas and write code that is simple and efficient~.

The testing technology stack used in this article: Angular12 Jasmine. Although the syntax of other testing technologies is different, the overall idea is similar. [Related tutorial recommendations: "angular tutorial"]

Tips: Jasmine test case determination, what are the methods, you can find it here, Poke me

Unit test

The component, by default, is the instance of the object to be tested created by Angular using the following syntax

beforeEach(() => { 
  fixture = TestBed.createComponent(BannerComponent); 
  component = fixture.componentInstance; 
  fixture.detectChanges(); 
});

Function test

1. Function call with no return value

function test(index:number ,fn:Function){
 if(fn){
     fn(index);
 }
}

How to test?

Counter example: Directly test the return value undefined

  const res = component.test(1,() => {}));
  expect(res).tobeUndefined();

Recommended practice:

 # 利用Jasmine
 it('should get correct data when call test',() =>{
     const param = {
       fn:() => {}
    }
   spyOn(param,'fn')
   component.test(1,param.fn);
   expect(param.fn).toHaveBeenCalled();
 })

Structural instruction HostListener test

Structure instructions, commonly used words hide, show, and for loop display such functions

 # code
 @Directive({ selector: '[ImageURlError]' })
export class ImageUrlErrorDirective implements OnChanges {
  constructor(private el: ElementRef) {}
  
  @HostListener('error')
  public error() { 
      this.el.nativeElement.style.display = 'none';
  } 
}

How to test?

Test idea:

  • The picture is triggered only when there is an error in loading, then find a way to trigger the error
  • Commands are generally attached to Use it on the component. On the component image element, just use errorEvent under dispath
#1.添加一个自定义组件, 并添加上自定义指令
@Component({
  template: `<div>
    <image src="https://xxx.ss.png" ImageURlError></image>
  </div>`
})
class TestHostComponent {

}

#2.把自定义组件视图实例化,并派发errorEvent
beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
        declarations: [
            TestHostComponent,
            ImageURlError
        ]
    });
}));

beforeEach(() => { 
 fixture = TestBed.createComponent(TestHostComponent); 
 component = fixture.componentInstance; 
 fixture.detectChanges();
});
  
it('should allow numbers only', () => {
    const event = new ErrorEvent('error', {} as any);
    const image = fixture.debugElement.query(By.directive(ImageURlError));
    image.nativeElement.dispatchEvent(event); //派发事件即可,此时error()方法就会被执行到
});

Make good use of public, private, protected modifiers

angular If it is modified by public, spec.ts can be accessed; but if it is modified by private or protected, it cannot be accessed;

Knock on the blackboard

  • If you plan to do unit testing and test each method, then please use public appropriately --- Difficulty *
  • If you do not plan to test each method, you can organize the data, call the entrance, and integrate the methods Test--Difficulty***

Test click event

The click event is triggered by direct js call to click, or by imitating the mouse to trigger click. event.

# xx.component.ts
@Component({
 selecotr: 'dashboard-hero-list'
})
class DashBoardHeroComponent {
    public cards = [{
        click: () => {
            .....
        }
    }]
}
# html
<dashboard-hero-list [cards]="cards"  class="card">
</dashboard-hero-list>`

How to test?

Testing ideas:

  • Test the component directly without using Host
  • Use the collection of objects containing click events returned by the code and call them one by one click, so that code coverage will be improved
it('should get correct data when call click',() => {
    const cards = component.cards;
    cards?.forEach(card => {
        if(card.click){
            card.click(new Event('click'));
        }
    });
    expect(cards?.length).toBe(1);
});

Other click reference ideas:

Idea 1:

  • Use TestHostComponent, Wrap the component that needs to be tested
  • and then use fixture.nativeElement.querySelector('.card') to find the click element bound to the component; on the
  • element, trigger dispatchEvent, that's it,

Idea 2:

  • Test the component directly without using Host

  • Then use fixture.nativeElement.querySelector(' .card'), find the bound click element;

  • UsetriggerEventHandler('click');

Update For more programming related knowledge, please visit: programming video! !

The above is the detailed content of 4 tips for writing Angular unit tests, come and take a look!. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete