Angular 8中@Output属性的Jasmine单元测试配置及问题求助
Hey there! I see you're diving into Angular unit testing for the first time—great job getting started! The "position of undefined" error you're hitting is because your checkEmployeePosition input property isn't being initialized in your tests, so when clickToCheck() runs, it tries to access this.checkEmployeePosition.level on an undefined value. Let's fix this and get your tests working properly.
First, Fix the Component Syntax
Your component class has a small syntax error—implements { is incomplete. If you don't need to implement any interfaces, you can just remove that part:
export class testComponent { // Removed the incomplete "implements {" @Output() passVal = new EventEmitter(); @Input() checkEmployeePosition: any; clickToCheck() { const testData = { position: this.checkEmployeePosition.level }; this.passVal.emit(testData); } }
Next, Fix the Test Issues
Let's walk through the changes needed in your testComponent.spec.ts:
Initialize the Input Property
In yourbeforeEachblock (or individual test cases), set a value forcheckEmployeePositionso it's not undefined:beforeEach(() => { fixture = TestBed.createComponent(testComponent); component = fixture.componentInstance; // Add this line to initialize the input component.checkEmployeePosition = { level: "senior" }; // Or any value you want to test de = fixture.debugElement; btn = de.query(By.css("button")); fixture.detectChanges(); // Trigger change detection to apply the input });Fix Invalid Test Code
- Your second test calls
component.emitContinue()—this method doesn't exist in your component! It should becomponent.clickToCheck(). - All your tests expect
passVal.emitto be called with1, but your component emits an object like{ position: "senior" }(matching thelevelvalue you set). Update your expectations to match the actual emitted data structure.
- Your second test calls
Here's the Full Corrected Spec File
import { DebugElement, ElementRef } from "@angular/core"; import { TestBed, ComponentFixture } from "@angular/core/testing"; import { By } from "@angular/platform-browser"; import { testComponent } from "./testComponent.component"; fdescribe("testComponent", () => { let fixture: ComponentFixture<testComponent>; let component: testComponent; let de: DebugElement; let btn: ElementRef; beforeEach(() => { TestBed.configureTestingModule({ declarations: [testComponent], }); }); beforeEach(() => { fixture = TestBed.createComponent(testComponent); component = fixture.componentInstance; // Initialize the input property to avoid undefined errors component.checkEmployeePosition = { level: "senior" }; de = fixture.debugElement; btn = de.query(By.css("button")); fixture.detectChanges(); // Apply the input value to the component }); it("should create", () => { expect(component).toBeTruthy(); }); describe("passVal output", () => { it("should emit the correct object when the button is clicked", () => { spyOn(component.passVal, "emit"); btn.nativeElement.click(); // Expect the emitted object to match the structure from clickToCheck() expect(component.passVal.emit).toHaveBeenCalledWith({ position: "senior" }); }); it("should emit the correct object when clickToCheck() is called directly", () => { spyOn(component.passVal, "emit"); component.clickToCheck(); // Fixed the method name here expect(component.passVal.emit).toHaveBeenCalledWith({ position: "senior" }); }); it("should emit the correct object when button is clicked (using subscribe)", () => { let emittedData: any; component.passVal.subscribe(data => { emittedData = data; }); btn.nativeElement.click(); expect(emittedData).toEqual({ position: "senior" }); }); }); });
Key Takeaways
- Always initialize
@Inputproperties in your tests if your component uses their properties (likelevelhere). - Make sure your test expectations match the actual data your component produces—your component emits an object, not a number!
- Double-check method names in tests to ensure they match what's in your component.
内容的提问来源于stack exchange,提问作者Mr. Learner

