Angular10 属性指令模拟不起作用。尝试获取模板中的元素:无法读取 null 的属性(读取“nativeElement”)

问题描述 投票:0回答:1

我正在尝试使用 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);
       }}
angular unit-testing jasmine angular-directive
1个回答
0
投票

您可以尝试将您的

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

© www.soinside.com 2019 - 2024. All rights reserved.