我正在尝试使用 Angular 10 在我的 jasmine 单元测试中模拟指令。该指令根据输入评估条件,并根据条件渲染或不渲染模板。使用模拟指令,我期望忽略“烦人的指令”,并能够获取本机元素。然而,它似乎并没有嘲笑它。如果我从模板中删除包含烦人指令的 div 并替换为注释掉的 div,则一切正常。该指令使用商店,但我不明白为什么我需要模拟它。谢谢!
要测试的组件的html模板
<div *annoyingDirective="input_data1; input_data2: true" class="class1">
<!--<div class="class1">-->
<div class="class2" >I'm trying to get this element
<mat-slide-toggle
[checked]="isChecked"
class="test-toggle"
(change)="toggleSlide($event)"
>
</mat-slide-toggle>
</div>
</div>
单元测试
@Directive({
selector: '[annoyingDirective]'
})
export class MockAnnoyingDirective {
@Input() input_data1: string[];
@Input('input_data2') input_data2: boolean = false;
}
describe('ComponentToTest', () => {
let component: ComponentToTest;
let fixture: ComponentFixture<ComponentToTest>;
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [MatSlideToggleModule, TranslateModule.forRoot()],
declarations: [ComponentToTest, MockAnnoyingDirective],
providers: [..add providers]
]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ComponentToTest);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('Should create component', () => {
expect(component).toBeTruthy(); //no errors
});
describe('slide-toggle-selection', () => {
it('should show the div', () => {
const forTest = fixture.debugElement.query(By.css(".class2")).nativeElement;
expect(forTest).toBeTruthy(); //TypeError: Cannot read properties of null
});
});
烦人的指令
@Directive({
selector: '[annoyingDirective]'
})
export class annoyingDirective implements OnInit, OnDestroy {
@Input() input_data1: string[];
@Input('input_data2') strictAccess: boolean = false;
//it uses a store - do I need to mock this??
@Select(UserState.permissions) permissions$: Observable<any[]>;
constructor(private viewContainer: ViewContainerRef, private templateRef: TemplateRef<any>)
{}
ngOnInit(){
if(some condition based on permissions is met)
return this.viewContainer.createEmbeddedView(this.templateRef);
}}
您可以尝试将您的
MockAnnoyingDirective
更改为以下内容吗?
@Directive({
selector: '[annoyingDirective]'
})
export class MockAnnoyingDirective implements OnInit {
@Input() input_data1: string[];
@Input('input_data2') input_data2: boolean = false;
constructor(
private readonly templateRef: TemplateRef<any>,
private readonly viewContainer: ViewContainerRef
) {}
ngOnInit(): void {
this.viewContainer.createEmbeddedView(this.templateRef);
}
}
由于
AnnoyingDirective
是一个结构指令(以 * 开头),因此在模拟中,我们必须绘制该指令所附加的内容(ngOnInit
中的 MockAnnoyingDirective
),否则我们将没有 div
。