【发布时间】:2019-06-12 12:35:44
【问题描述】:
首先,有很多类似的问题(1、2、3、4、5、6、7、8 等等),但实际上没有一个答案适用于我的案例,而且许多其他的根本没有答案。
说明和源代码链接
以下代码是much bigger project 的简单Minimal, Reproducible Example。
当从项目目录运行npm run test时
- 预期结果:
- 所有测试通过没有错误
- 实际行为:
- 在 Chromium 中,下面注释为
// FAILING TEST!的测试未通过并报告Uncaught Error: ViewDestroyedError: Attempt to use a destroyed view(link to travis report in the real project) - 在 Google Chrome 中测试通过,但如果您打开控制台 (F12),您会看到记录了相同的错误(因此这也失败了,但 Chrome 将其吞下)。
- 在 Chromium 中,下面注释为
代码
app.component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
hide: boolean = false;
someSubscription: Subscription;
constructor(private appServiceService: AppServiceService) { }
ngOnInit() {
this.someSubscription = this.appServiceService.shouldHide().subscribe(shouldHide => this.hide = shouldHide);
}
ngOnDestroy() {
this.someSubscription.unsubscribe();
}
}
app.component.html
<div class="row" id="jmb-panel" *ngIf="!hide">
Hello
</div>
app.component.spec
describe('AppComponent', () => {
let component: AppComponent;
let componentDe: DebugElement;
let fixture: ComponentFixture<AppComponent>;
const behaviorSubject = new BehaviorSubject<boolean>(false);
const appServiceStub = {
shouldHide: () => { spy.shouldHideSpyFn(); return behaviorSubject.asObservable() }
};
const spy = { shouldHideSpyFn: () => { } };
let spyShouldHide: jasmine.Spy;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
schemas: [NO_ERRORS_SCHEMA],
providers: [{ provide: AppServiceService, useValue: appServiceStub }]
}).compileComponents();
}));
beforeEach(() => {
behaviorSubject.next(false);
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
componentDe = fixture.debugElement;
fixture.detectChanges();
spyShouldHide = spyOn(spy, 'shouldHideSpyFn');
});
it('should call AppServiceService#shouldHide on init', () => {
component.ngOnInit();
fixture.detectChanges();
expect(spyShouldHide).toHaveBeenCalledTimes(1);
});
it('should not render div if the AppServiceService#shouldHide observables emit true', () => {
appServiceStub.shouldHide().subscribe((li) => {
if (li) {
fixture.detectChanges();
expect(componentDe.query(By.css('#jmb-panel'))).toBeNull();
}
});
behaviorSubject.next(true);
});
// FAILING TEST!
it('should render div if the AppServiceService#shouldHide observables emit true', () => {
appServiceStub.shouldHide().subscribe((li) => {
if (!li) {
fixture.detectChanges();
expect(componentDe.query(By.css('#jmb-panel'))).not.toBeNull('Jumbotron panel should not be null');
}
});
behaviorSubject.next(false);
});
it('should create', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
});
});
补充说明:
在发布的规范中指定测试的顺序很重要!如果更改测试顺序,则所有测试都可能通过。这是不正确的:所有测试都应该独立于它们指定的顺序通过。事实上,在实际项目中,测试是随机失败的:当 jasmine 建立的测试顺序是这样设置的。因此,我无法通过更改测试顺序来“解决”这个问题。
问题
-
为什么会发生这个错误,这是什么意思?,更重要的是,
-
在angular 中实施测试时,我们如何避免/修复此错误?
【问题讨论】:
-
不确定它是否能解决您的问题,但我没有看到您的规范调用
ngOnInit(或再次调用detectChanges)的理由。 -
@TheHeadRush,yurzui 发布的答案有关键。另一方面,您的评论是正确的。再次感谢。
标签: angular angular unit-testing jasmine karma-jasmine karma-runner