angular: Running Jasmine tests: TypeError: Cannot read property 'nativeElement' of null
I’m submitting a…
[ ] Regression (a behavior that used to work and stopped working in a new release)
[x ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
If you have an *ngIf on an element, you cannot get the element via -> fixture.debugElement.query(By.css(‘.welcome’));
I am even setting the value of welcome in the beforeEach() method and it still will not resolve to true on *ngIf=“welcome”
Expected behavior
*ngIf should resolve to true and element should be found and not null.
Minimal reproduction of the problem with instructions
I modified the Angular testing sample:
Please see the WelcomeComponent failure. https://plnkr.co/edit/txk3ZCOatFKqoRcjOofL?p=preview
To make it fail I added *ngIf to the H3 in welcome.component.ts. Without *ngIf it will not fail.
@Component({
selector: 'app-welcome',
template: '<h3 *ngIf="welcome" class="welcome" ><i>{{welcome}}</i></h3>'
})
In the welcome.component.spec.ts I set the value of welcome so the *ngIf="welcome" shoudl resolve to true.
userService = fixture.debugElement.injector.get(UserService);
componentUserService = userService;
// UserService from the root injector
userService = TestBed.get(UserService);
**comp.welcome = 'test';**
// get the "welcome" element by CSS selector (e.g., by class name)
de = fixture.debugElement.query(By.css('.welcome'));
el = de.nativeElement;
What is the motivation / use case for changing the behavior?
Environment
@angular/cli: 1.4.1
node: 8.2.1
os: win32 x64
@angular/animations: 4.3.6
@angular/common: 4.3.6
@angular/compiler: 4.3.6
@angular/compiler-cli: 4.3.6
@angular/core: 4.3.6
@angular/forms: 4.3.6
@angular/http: 4.3.6
@angular/platform-browser: 4.3.6
@angular/platform-browser-dynamic: 4.3.6
@angular/platform-server: 4.3.6
@angular/router: 4.3.6
@angular/cli: 1.4.1
: 1.5.0
typescript: 2.4.1
Browser:
- [x ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
For Tooling issues:
node: 8.2.1
Windows
Others:
See the modified Angular testing plunkr I created.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 22 (2 by maintainers)
Why is this closed? I just started Unit Testing in Angular 5 and this issue immediately presents itself ie
Was there ever a suitable resolution for this issue?
Fast forward several months and it’s still prevalent and causing me issues (Angular 5, Karma 1.7.1 and Jasmine 2.8.0)
Thanks
Sorry for the late reply.
Resolution:-
it(‘productSelection’, async(() => { spyOn(component, ‘productSelection’); const btn = fixture.debugElement.query(By.css(‘.BPNormal’)); btn.triggerEventHandler(‘click’, ‘productSelection’); fixture.whenStable().then(() => { expect(component.productSelection).toHaveBeenCalled(); }); }));
On Fri, Dec 7, 2018 at 6:32 PM choubani amir notifications@github.com wrote:
Workaround If you are using
*ngIf
in the element, usehidden
instead.<h2 [hidden]="hideItem"> My Message</h2>
This error is caused when jasmine could not find that element in the DOM. The most common scenario is using
*ngIf
in the template. According to docs, *ngIf destroys the element from DOM, if the expression evaluates to false.Why is this closed? This is still a problem Friday Jan 25, 2019
Hello. I solved this problem by using
fakeAsync
call.@jrmcdona - after setting comp.welcome = ‘test’; - try using
fixture.detectChanges()
in test suite. This may help you, as by default, Test components don’t run change detection automatically. To enable auto change detection - usefixture.autoDetectChanges()
in beforeEach function.I’ve found out what was my issue: the element I was trying to get wasn’t defined in the template at the moment that I tried to get it. In my case, I was trying to get a button inside a td, but my table was empty because I didn’t populate it with mock data.
Using a debugger, I could see that fakeAsync() and async() just make the compiler keep waiting for something that never comes, until the testing process ends and makes it seem like the test passed, but in reality it just didn’t run.
This issue is closed by the OP him/herself, feel free to open a new issue with minimal reproduction.
All, if using change-detection OnPush on the component, refer this ancient issue https://github.com/angular/angular/issues/12313 . In short, when using OnPush in the component, let the constructor’s ChangeDetectorRef be public. In the test, when you change a component’s member, do component.changeDetector.detectChanges()