是否可以在Angular中模拟属性指令?

时间:2017-06-12 08:50:08

标签: angular jasmine

我有以下指令应用于输入标记。当在主机组件上运行jasmine规范时,我希望它忽略(模拟)这个指令,因为它依赖于我对测试不感兴趣的jquery。

我曾尝试创建MockDirective课程,但没有成功。谁知道怎么做到这一点?

@Directive({
    selector: '[skinColorPicker]'
})
export class ColorPickerDirective implements OnInit {

    @Input('skinColorPicker') initialColor;

    @Output() colorSelected: EventEmitter<string> = new EventEmitter<string>();

    constructor(private el: ElementRef) {}

    ngOnInit() {

       // legacy jQuery blah blah
    }
}

主持人:

<input skinColorPicker="'#555'" (colorSelected)="onPageBackgroundColorSelected($event)" 
 />

规范:

describe('PrintSidebarComponent', () => {
  let component: PrintSidebarComponent;
  let fixture: ComponentFixture<PrintSidebarComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
          PrintSidebarComponent,
          MockDirective({ selector: '[skinColorPicker]' }) // does not work
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(PrintSidebarComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

export function MockDirective(options: Component): Component {
    let metadata: Directive = {
        selector: options.selector,
        inputs: options.inputs,
        outputs: options.outputs
    };
    return Directive(metadata)(class _ { });
}
  

无法绑定到'skinColorPicker',因为它不是已知的属性   “输入”。

我看到this overrideDirective method,但未能找到一个合适的例子。

一个解决方案 原来是@Input('skinColorPicker')属性的缺失模拟声明:

MockDirective({selector: '[skinColorPicker]', inputs: ['skinColorPicker']})

我仍然认为看一个内置Testbed.overrideDirective函数的例子会更好。

Plunkr

4 个答案:

答案 0 :(得分:3)

我的解决方案与@ jenson-button-event的解决方案相同,只有一些细微的更改,因此它会在TypeScript中编译。

export function MockDirective(options: Component): Directive {
  const metadata: Directive = {
    selector: options.selector,
    inputs: options.inputs,
    outputs: options.outputs
  };
  return <any>Directive(metadata)(class _ {}); // <----- add <any>
}

TestBed.configureTestingModule({
  declarations: [
      PrintSidebarComponent,
      MockDirective({ 
        selector: '[skinColorPicker]', 
        inputs: []  // <--- empty, unless the directive has inputs
      })
  ]
})

答案 1 :(得分:2)

MockDirective确实有效,但配置错误。

export function MockDirective(options: Component): Directive {
    const metadata: Directive = {
        selector: options.selector,
        inputs: options.inputs,
        outputs: options.outputs
    };
    return Directive(metadata)(class _ { });
}

原来是@Input('skinColorPicker')属性的缺失模拟声明:

TestBed.configureTestingModule({
  declarations: [
      PrintSidebarComponent,
      MockDirective({ 
        selector: '[skinColorPicker]', 
        inputs: ['skinColorPicker'] }) // does work
  ]
})

答案 2 :(得分:1)

由于Component是没有模板的指令,我们可以直接使用MockComponent。我想是&#39; MockDirective&#39;也受到它的启发。

将MockComponent用于mock指令的方法如下:

MockComponent({
  selector: '[skinColorPicker]',
  inputs: ['skinColorPicker']
}),

答案 3 :(得分:1)

此解决方案与@ jenson-button-event和@maia的解决方案完全相同,不同之处在于改进了Typescript的正确性。没有这些改进,对我来说是行不通的。

export function MockDirective(options: Component): Type<Directive> {
  const metadata: Directive = {
    selector: options.selector,
    inputs: options.inputs,
    outputs: options.outputs,
  };
  return Directive(metadata)(class MockDirectiveClass {
  });
}

TestBed.configureTestingModule({
  declarations: [
      PrintSidebarComponent,
      MockDirective({ 
        selector: '[skinColorPicker]', 
        inputs: []  // <--- empty, unless the directive has inputs
      })
  ]
})