Puddlejumper26
Puddlejumper26

Reputation: 77

How to unit test a generic component in Angular

I am writing a test for AppleComponent, and which has type <T,U extends BananaComponent<T>>. And there is BananaComponent<T>

target component

export class AppleComponent<T,U extends BananaComponent<T>>{
   public appleA = 'appleA';
   public appleB = 'appleB';
   public appleC !: U;

}

extended component

export abstract class BananaComponent<T> implements OnInit{
   public bananaA = 'bananaA';
   public bananaB = 'bananaB';
}

Here is my spec file for testing AppleComponent

import { CommonModule } from '@angular/common';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import {AppleComponent} from '....';
import {BananaComponent} from '....';

describe('AppleComponent', () => {
   let component: AppleComponent;
   let fixture: ComponentFixture<AppleComponent>;

   beforeEach(()=>{
     TestBed.configureTestingModule({
         declarations:[AppleComponent],
         imports:[BananaComponent],
     });
     fixture = TestBed.creatComponent(AppleComponent);
     component = fixture.componentInstance;
   });

   it('should with defaults',() => {
      expect(component.appleA).toBe('appleA','appleA has appleA as default value'); // passes
   });
});

Therefore I have a problem with the spec file, it could not be compiled.

My logic is the types of component and fixture are wrong,I figured I need to change something to the component and fixture, then came to the answer I wrote below.

// first inside the test to define a random type, then give it to AppleComponent, and BananaComponent.

type typeA = { };  
type typeModel = AppleComponent<typeA, BananaComponent<typeA>>;   

let component: typeModel; 
let fixture: ComponentFixture<typeModel>

Upvotes: 3

Views: 3300

Answers (2)

Puddlejumper26
Puddlejumper26

Reputation: 77

My misunderstanding about this concept is:

AppleComponent is not really extending from BananaComponent, therefore component. will never be able to obtain anything from BananaComponent.

What is happnening here is just the type of AppleComponent extends the BananaComponent; The purpose is to keep the type of the input value inside the AppleComponent to be identical with the type of input value inside BananaComponent.

Therefore during the test it is still need to write the component, fixture in a right way.

Solution for my quesiton I asked

// first inside the test to define a random type, then give it to AppleComponent, and BananaComponent.

type typeA = { };  
type typeModel = AppleComponent<typeA, BananaComponent<typeA>>;   

let component: typeModel; 
let fixture: ComponentFixture<typeModel>

And for a better understanding of the relationship between the types of AppleComponent and BananaComponent, here are the more detailed codes.

AppleComponent

export class AppleComponent<T,U extends BananaComponent<T>>{
   public appleA = 'appleA';
   public appleB = 'appleB';
   public applePurchase !: U;
}

BananaComponent

export abstract class BananaComponent<T> implements OnInit{
   public bananaA = 'bananaA';
   public bananaB = 'bananaB';
   public bananaPurchase : T;

   public totalPurchase: T;
}

from the above code, we could see that

  1. inside BananaComponent, type T is to make sure the input bananaPurchase has the same type with totalPurchase, e.g. when bananaPurchase = 1000; then the type is set to number, then the value of totalPurchase has to be a number as well, and vice versa.

  2. same situation inside AppleComponent, because it extends the type from BananaComponent, therefore it means the applePurchase should have the same type with bananaPurchase and totalPurchase.

Upvotes: 4

Yvan
Yvan

Reputation: 1121

Did you try to give the type of your component during the creation ?

fixture = TestBed.createComponent<AppleComponent<TestObject>>(AppleComponent)

You should probably create a TestObject Model won't work with generic Type T.

export class TestObject {

}

Upvotes: 9

Related Questions