I am having problems while performing a simple unit test in my NX workspace. What I am attempting to do is to 1) configure TestBed and 2) Inject service. However, even if I use scaffolded dummy service, the test still fails as the injected service is said to be undefined
test.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TestService {
constructor() { }
}
test.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { TestService } from './test.service';
describe('TestService', () => {
let service: TestService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ TestService ]
});
service = TestBed.inject(TestService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
Does anybody have an idea why is this happening? What exactly is the problem here?
Edit: Yes, I do know I can create a mock. However, the issue still seems strange to me so I would like to get to the bottom of it rather than finding a workaround.
Edit 2:
Using ng test <project> --test-file=<filename> directly yields the same results are using NXCLI to perform tests
Edit 3: I shared my code on StackBlitz as requested: https://stackblitz.com/edit/ng-unittest-issue
I've passed through the exact same issues, where the service was undefined when being tested.
What solved my problem here were two things:
jest.mock('@angular/core/testing') from your code. This was required on earlier versions.TestBed.configureTestingModule.Here is a sample functional code and unit testing for a simple Http service, tested on Angular 9 and Angular 10:
api.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ApiService {
constructor(private http: HttpClient) {}
baseUrl = 'https://my-api-url.com';
//api/getId/:id
getDataById(id: number): Observable<DataSample[]> {
return this.http.get<DataSample[]>(`${this.baseUrl}/getId/${id}`);
}
}
export interface DataSample {
id: number;
name: string;
}
api.service.spec.ts
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { ApiService, DataSample } from './api.service';
describe('ApiService tests', () => {
let service: ApiService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [ApiService],
});
service = TestBed.inject(ApiService);
httpMock = TestBed.inject(HttpTestingController);
});
afterEach(() => httpMock.verify());
it('should return an Observable<DataSample[]>', () => {
expect(service).toBeTruthy();
const id: number = 1;
const mockResult: DataSample[] = [
{
id: 1,
name: 'name1',
},
{
id: 2,
name: 'name2',
},
];
const expectedUrl = `https://my-api-url.com/getId/${id}`;
service
.getDataById(id)
.subscribe((res) => expect(res).toBe(mockResult));
const req = httpMock.expectOne(expectedUrl);
expect(req.request.method).toBe('GET');
req.flush(mockResult);
});
});
Hope it helps 😉
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With