Reputation: 521
I am trying to unit test a "add object" (add dish) component in Angular 6. With my current code I get the error "Cannot read property 'dishForm' of undefined".
So, it seems it does the DishAddComponent is not recognized as the component to be tested? Can anybody help me out with this? Thanks in advance!
I've also tried (amongst others) adding async to beforeEach, as described here: Angular 2 Testing - Component Instance is undefined , but it does not work.
Angular Component to be Unit Tested:
export class DishAddComponent implements OnInit {
public dishForm: FormGroup;
constructor(private dishService: DishService,
private formBuilder: FormBuilder,
private router: Router) { }
ngOnInit() {
// define dishForm (with empty default values)
this.dishForm = this.formBuilder.group({
name: ['', [Validators.required, Validators.maxLength(30), Validators.pattern('[a-zA-Z :]*')]],
country: [''],
ingredients: this.formBuilder.array([]),
recipe: ['', [Validators.required, Validators.minLength(50)]],
}, { validator: CustomValidators.DishNameEqualsCountryValidator });
}
addIngredient(): void {
let ingredientsFormArray = this.dishForm.get('ingredients') as FormArray;
ingredientsFormArray.push(IngredientSingleComponent.createIngredient());
}
addDish(): void {
if (this.dishForm.dirty && this.dishForm.valid) {
let dish = this.dishForm.value;
this.dishService.addDish(dish)
.subscribe(
() => {
this.router.navigateByUrl('/dishes');
});
}
}
}
Unit Test in Jest:
describe('DishAddComponent', () => {
let component: DishAddComponent;
let fixture: ComponentFixture<DishAddComponent>;
let formGroup: FormGroup;
let formBuilderMock: any;
let dishServiceMock: any;
beforeEach(() => {
formBuilderMock = {
group: jest.fn().mockName('formBuilderMock.group'),
array: jest.fn().mockName('formBuilderMock.array')
};
dishServiceMock = {
addDish: jest.fn().mockName('dishServiceMock.addDish')
};
TestBed.configureTestingModule({
imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule.withRoutes(routes)],
declarations: [ DishAddComponent, IngredientSingleComponent ],
providers:
[
{ provide: FormBuilder, useValue: formBuilderMock },
{ provide: FormGroup, useValue: formGroup },
{ provide: DishService, useValue: dishServiceMock }
]
});
fixture = TestBed.createComponent(DishAddComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('form invalid when empty', () => {
(console).log(component);
expect(component.dishForm.valid).toBeFalsy();
});
});
EDIT: If I use the code below, I get an error as well:
DishAddComponent › should create
expect(received).toBeTruthy()
Received: undefined
it('should create', () => {
expect(component).toBeTruthy();
});
Upvotes: 5
Views: 23640
Reputation: 521
In the end I got rid of the "undefined error" with the code below. I needed to mock one of the childcomponents and create an instance of formbuilder. Thanks for the tips!
describe('DishAddComponent', () => {
let component: DishAddComponent;
let fixture: ComponentFixture<DishAddComponent>;
let dishServiceMock: any;
// mock singleingredientcomponent
@Component({
selector: 'app-ingredient-single',
template: '<div></div>',
})
class MockSingleIngredientComponent {
@Input() public ingredientIndex: number;
@Input() public ingredient: FormGroup;
}
// create new instance of FormBuilder
const formBuilder: FormBuilder = new FormBuilder();
beforeEach(async(() => {
dishServiceMock = {
addDish: jest.fn().mockName('dishServiceMock.addDish'),
addIngredient: jest.fn().mockName('dishServiceMock.addIngredient')
};
TestBed.configureTestingModule({
imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule.withRoutes([])],
declarations: [ DishAddComponent, MockSingleIngredientComponent ],
providers:
[
{ provide: FormBuilder, useValue: formBuilder },
{ provide: DishService, useValue: dishServiceMock }
]
})
.compileComponents();
}));
beforeEach(() => {
// create component and test fixture
fixture = TestBed.createComponent(DishAddComponent);
// get test component from the fixture
component = fixture.componentInstance;
// ..
fixture.detectChanges();
});
// unit tests
it('should create', () => {
expect(component).toBeTruthy();
});
});
Upvotes: 3
Reputation: 44
Try to compile components by adding compileComponents() after configureTestingModule()
TestBed.configureTestingModule({
imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule.withRoutes(routes)],
declarations: [ DishAddComponent, IngredientSingleComponent ],
providers:
[
{ provide: FormBuilder, useValue: formBuilderMock },
{ provide: FormGroup, useValue: formGroup },
{ provide: DishService, useValue: dishServiceMock }
]
})
.compileComponents();
Upvotes: 1