【问题标题】:spyOn not working with async pipe in AngularspyOn 不能在 Angular 中使用异步管道
【发布时间】:2021-05-13 12:09:18
【问题描述】:

我有一个运行良好的简单组件,如下所示:

@Component({
  selector: 'component',
  template: `
    {{userWithAsyncPipe | async | json}} <!-- = null in test -->
    {{userFromOnInit | json}} <!-- working test -->
  `,
})
export class Component implements OnInit {
  constructor(private service: MyService) {
  }

  userWithAsyncPipe = this.service.getUser();
  userFromOnInit;

  ngOnInit() {
    this.service.getUser().subscribe(user => this.userFromOnInit = user);
  }
}

我试图通过模拟service.getUser() 方法来测试它。所以我写了一个大致如下所示的测试组件:

describe('', () => {

  ...
  let myService;
  beforeEach(() => {
    myService = TestBed.inject(MyService);
  });

  it('', () => {
    spyOn(myService, 'getUser').and.returnValue(of({name: 'Jacob'}));
  });
});

但是当我查看 karma 浏览器时,只有变量 userFromOnInit 被解析。 userWithAsyncPipe 等于 null

这是什么鬼?

【问题讨论】:

  • 你能添加完整的测试台设置吗?
  • 也请看这里,它有一个如何测试类似代码的示例ng-mocks.sudo.eu/extra/mock-observables
  • 我会尝试,但它是 Angular,它涉及很多代码......谢谢你的例子,但它不使用 |异步管道。
  • 它不应该使用它。这个想法是你用MockProvider提供一个假主题,asyncCommonModule提供。

标签: angular typescript jasmine


【解决方案1】:

ng-mocks 有一个例子供你参考

https://codesandbox.io/s/gallant-bas-is5zy?file=/src/test.spec.ts

import { CommonModule } from "@angular/common";
import {
  Component,
  EventEmitter,
  Input,
  NgModule,
  Injectable,
  Output
} from "@angular/core";
import { MockBuilder, MockInstance, MockRender, ngMocks } from "ng-mocks";
import { EMPTY, Observable, of } from "rxjs";

@Injectable()
class MyService {
  getUser(): Observable<any> {
    return EMPTY;
  }
}

@Component({
  selector: "app-target",
  template: `
    {{ userWithAsyncPipeFn() | async | json }}
    {{ userWithAsyncPipe | async | json }}
    {{ userFromOnInit | json }}
  `
})
class TargetComponent {
  userWithAsyncPipeFn = () => this.service.getUser();
  userWithAsyncPipe = this.service.getUser();
  userFromOnInit: any;

  constructor(private service: MyService) {}

  ngOnInit() {
    this.service.getUser().subscribe((user) => (this.userFromOnInit = user));
  }
}

@NgModule({
  imports: [CommonModule],
  declarations: [TargetComponent],
  providers: [MyService]
})
class TargetModule {}
describe("my sandbox", () => {
  beforeEach(() => MockBuilder(TargetComponent, TargetModule));

  it("should do something", () => {
    MockInstance(MyService, "getUser", () => of({ name: "Jacob" }));

    const fixture = MockRender(TargetComponent);
    expect(fixture.nativeElement.innerHTML.match(
      /\{\s*"name":\s*"Jacob"\s*\}/g
    ).length).toEqual(3);
  });
});

【讨论】:

  • 非常感谢。但是有没有办法避免安装依赖项?
  • 如果你想在it做,你需要在beforeEach正确配置TestBed,不要在任何地方调用createComponent,然后在it注入服务,根据需要模拟,并且只有在它调用createComponentdetectChanges之后,在这种情况下它应该具有与上例相同的效果。
  • 哇...好吧,我明白为什么它现在不起作用了。这说得通。我不明白为什么我在 Web 的任何地方都没有发现这个问题。无论如何,非常感谢你!
猜你喜欢
  • 2020-03-26
  • 2018-07-02
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多