You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

请求协助完成AdminService中getUsers方法的Angular单元测试

Angular Unit Test for getUsers Method in AdminService

I'm stuck trying to write a proper unit test for the getUsers method in my AdminService. I've gone through numerous testing resources but haven't found anything that helps me move forward. Here's the relevant code from my service:

admin.service.ts

private bcUrl = 'http://30.30.0.101:8080';
private httpOptions = {
 headers: new HttpHeaders({
 'Content-Type': 'application/json',
 'Authorization': this.cookieService.get('token')
 })
};
constructor(
 private http: HttpClient,
 private cookieService: CookieService,
 private userService: UserService
) { }
getUsers(page, lim): any {
 return this.http.get(`${this.bcUrl}/api/security/users?page=${page}&size=${lim}`, this.httpOptions)
 .subscribe(
 (data: DataInterface) => {
 this.users = data.content;
 this.st.totalElements = data.totalElements;
 this.st.totalPages = data.totalPages;
 this.dataSource = data.content;
 },
 error => {
 if (error.status === 404) {
 alert('Сторінка не знайдена');
 }
 if (error.status === 401) {
 alert('Немає прав доступу');
 }
 });
}

I've started writing the test code but don't know how to proceed. Here's what I have so far:

Current Test Code

import {async, getTestBed, inject, TestBed} from '@angular/core/testing';
import {CookieService} from 'ngx-cookie-service';
import {AdminService} from './admin.service';
import {HttpClientTestingModule} from '@angular/common/http/testing';
import {UserService} from '@app/core/user/user.service';
import {RequestMethod, ResponseOptions} from '@angular/http';
describe('AdminService', () => {
 beforeEach(() => {
 TestBed.configureTestingModule({
 imports: [HttpClientTestingModule],
 providers: [AdminService, CookieService, UserService]
 });
 });

 it('should be created', inject([AdminService], (service: AdminService) => {
 expect(service).toBeTruthy();
 }));

 it('should be getUsers', async(() => {
 const adminService: AdminService = getTestBed().get(AdminService);
 mockBackend.connections.subscribe(connection => {
 expect(connection.request.method).toBe(RequestMethod.Delete);
 connection.mockRespond(
 new Response(new ResponseOptions()))
 });
 }));
});

Could someone help me complete this unit test, or recommend appropriate technical resources to guide me?


Solution

Let's fix and complete your unit test step by step:

1. Fix Imports and Core Setup

First, you're mixing the old @angular/http module with the modern @angular/common/http (used by HttpClientTestingModule). We'll use HttpTestingController instead of mockBackend, and mock CookieService to avoid relying on real browser cookies during tests.

Update your test setup:

import { async, TestBed } from '@angular/core/testing';
import { CookieService } from 'ngx-cookie-service';
import { AdminService } from './admin.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { UserService } from '@app/core/user/user.service';
// Import your DataInterface if it's defined in a separate file
import { DataInterface } from './path-to-your-data-interface';

describe('AdminService', () => {
  let adminService: AdminService;
  let httpTestingController: HttpTestingController;
  let cookieServiceSpy: jasmine.SpyObj<CookieService>;

  beforeEach(() => {
    // Create a spy for CookieService to mock token retrieval
    const cookieSpy = jasmine.createSpyObj('CookieService', ['get']);
    cookieSpy.get.and.returnValue('test-auth-token');

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        AdminService,
        { provide: CookieService, useValue: cookieSpy },
        UserService // If UserService has its own dependencies, mock it similarly
      ]
    });

    // Inject services for testing
    adminService = TestBed.inject(AdminService);
    httpTestingController = TestBed.inject(HttpTestingController);
    cookieServiceSpy = TestBed.inject(CookieService) as jasmine.SpyObj<CookieService>;
    // Mock window.alert to avoid actual browser popups during tests
    spyOn(window, 'alert');
  });

  // Clean up after each test to ensure no unmatched HTTP requests
  afterEach(() => {
    httpTestingController.verify();
  });

  it('should be created', () => {
    expect(adminService).toBeTruthy();
  });

2. Test Successful getUsers Call

Now let's test the happy path where the API returns valid user data:

it('should fetch users and update service properties on success', () => {
    const mockPage = 1;
    const mockLimit = 10;
    const mockResponse: DataInterface = {
      content: [{ id: 1, username: 'test-user-1' }, { id: 2, username: 'test-user-2' }],
      totalElements: 25,
      totalPages: 3
    };

    // Call the method under test
    adminService.getUsers(mockPage, mockLimit);

    // Verify the correct HTTP request is made
    const req = httpTestingController.expectOne(
      `${adminService['bcUrl']}/api/security/users?page=${mockPage}&size=${mockLimit}`
    );
    expect(req.request.method).toBe('GET');
    // Check that headers are correctly set
    expect(req.request.headers.get('Authorization')).toBe('test-auth-token');
    expect(req.request.headers.get('Content-Type')).toBe('application/json');

    // Respond with mock data
    req.flush(mockResponse);

    // Verify service state is updated correctly
    expect(adminService['users']).toEqual(mockResponse.content);
    expect(adminService['st'].totalElements).toBe(mockResponse.totalElements);
    expect(adminService['st'].totalPages).toBe(mockResponse.totalPages);
    expect(adminService['dataSource']).toEqual(mockResponse.content);
  });

3. Test Error Scenarios

Add tests for 404 and 401 error cases to ensure the correct alerts are triggered:

it('should show 404 alert when request fails with 404 status', () => {
    const mockPage = 1;
    const mockLimit = 10;

    adminService.getUsers(mockPage, mockLimit);

    const req = httpTestingController.expectOne(
      `${adminService['bcUrl']}/api/security/users?page=${mockPage}&size=${mockLimit}`
    );
    // Respond with 404 error
    req.flush('Page Not Found', { status: 404, statusText: 'Not Found' });

    expect(window.alert).toHaveBeenCalledWith('Сторінка не знайдена');
  });

  it('should show 401 alert when request fails with 401 status', () => {
    const mockPage = 1;
    const mockLimit = 10;

    adminService.getUsers(mockPage, mockLimit);

    const req = httpTestingController.expectOne(
      `${adminService['bcUrl']}/api/security/users?page=${mockPage}&size=${mockLimit}`
    );
    // Respond with 401 error
    req.flush('Unauthorized', { status: 401, statusText: 'Unauthorized' });

    expect(window.alert).toHaveBeenCalledWith('Немає прав доступу');
  });
});

Key Notes:

  • We use HttpTestingController to intercept and mock HTTP requests (built into HttpClientTestingModule).
  • Mocking CookieService ensures we don't depend on real browser state during tests.
  • Spying on window.alert lets us verify error messages without disrupting test execution.
  • Accessing private properties (like bcUrl or users) via bracket notation is acceptable for testing; for production code, consider adding public getters if you need to access these values elsewhere.

内容的提问来源于stack exchange,提问作者Виктор Кондратьев

火山引擎 最新活动