Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a component which contains a custom form control?

I got a component like this

@Component({
      selector: 'app-custom-form-control',
      templateUrl: '<input>',
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => SelectComponent),
          multi: true
        }
      ]
    })
export class CustomFormControlComponent implements ControlValueAccessor {...}

As you see it's a custom form control. I use it in a component which I'm going to test.

    @Component({
      selector: 'app-root',
      templateUrl: '<div [formGroup]="form">
          <app-custom-form-control formControlName="my_field"></app-custom-form-control>
      </div>',
    })
    export class AppComponent implements OnInit, OnDestroy {...}

So how can I mock app-custom-form-control for my test?

The current implementation needs a real component...

  beforeEach(async(() => {
    const testRouter = new RouterStub();
    const testDataService = new DataServiceStub();
    TestBed.configureTestingModule({
      declarations: [
        AppComponent,
        CustomFormControlComponent // it is a real stuff
      ],
      imports: [
        ReactiveFormsModule
      ],
      providers: [
        { provide: Router, useValue: testRouter },
        { provide: DataService, useValue: testDataService }
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
    }).compileComponents();
  }));

Otherwise(without declaration the component) I got an error Failed: No value accessor for form control with name: app-custom-form-control

like image 220
constantant Avatar asked Jun 12 '18 16:06

constantant


People also ask

How can we get an instance of the component to be tested?

The TestBed. createComponent() method is used to create an instance of the AppComponent. The spec then uses expect and matcher functions to see if the component produces the expected behavior. As a result, the spec will either pass or fail.

How do you write a unit test case for a custom validator for Angular reactive forms?

You can create a from group in your test with one formControl (in this case some input). Then leverage the setValue function of formControl to set a value that will pass the unit test. Then you can pass this form control to the validator function and assert that it returns null (should return null if there's no error).

How do you write a test case for reactive form?

Step 1: Get the login form from component. Step 2: Create a dummy login form default value object. Step 3: At-last, compare both the form group values with dummy object. Step 2: Get the username value from the component form builder.


1 Answers

When doing tests to Angular applications, there are two main approaches (and a mix) you can follow:

1- Stubbing unneeded components, where

(...) you create and declare stub versions of the components and directive that play little or no role in the tests (...)

2- The NO_ERRORS_SCHEMA which

(...) tells the Angular compiler to ignore unrecognized elements and attributes (...)

With this last one the compiler won't throw an error when it encounters the app-custom-form-control selector in the AppComponent template.

3- Use both techniques together

Selecting one approach or another, it's up to you, since it depends on the final goal you aim to with the test.


Applying approach 1 it would be something like this:

describe('AppComponent', () => {

// component stub
@Component({selector: 'app-custom-form-control', template: ''})
class CustomFormControlComponentStub {}
//...
  beforeEach(async(() => {
    const testRouter = new RouterStub();
    const testDataService = new DataServiceStub();
    TestBed.configureTestingModule({
      declarations: [
        AppComponent,
        CustomFormControlComponentStub // it is fake! stuff
      ],
      // ... code omitted
    }).compileComponents();
  }));
//...
});
like image 89
lealceldeiro Avatar answered Oct 05 '22 02:10

lealceldeiro