You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 2+中如何在不使用TestBed的情况下mock @select属性?

Mocking @select Properties in Angular Unit Tests Without TestBed

Great question! I’ve dealt with this exact scenario when striving to keep unit tests fast and focused on pure component logic—no TestBed required. Here are a few reliable approaches to mock those Redux @select-decorated Observable properties:

1. Directly Assign the Observable to the Component Instance

Most @select decorators create an instance property that you can overwrite directly after instantiating your component. This is the simplest approach for one-off mocks:

import { of } from 'rxjs';
import { MyComponent } from './my.component';
import { mockUser } from './mocks';

describe('MyComponent', () => {
  let component: MyComponent;

  beforeEach(() => {
    component = new MyComponent();
    // Overwrite the @select property with your test Observable
    component.user$ = of(mockUser);
  });

  it('should process user data correctly', () => {
    // Your test logic here, using the mocked user$ Observable
    component.somePureFunction();
    expect(...).toBe(...);
  });
});

If the decorator uses a getter/setter that blocks direct assignment, use Object.defineProperty to force the value:

Object.defineProperty(component, 'user$', {
  value: of(mockUser),
  writable: true,
  configurable: true
});

2. Mock the @select Decorator Globally

If you have multiple components using @select and want a reusable mock, override the decorator itself at the module level. For example, if you’re using @ngrx/store:

// At the top of your test file, before importing the component
jest.mock('@ngrx/store', () => ({
  Select: jest.fn(() => (target: any, propertyKey: string) => {
    // Initialize the property with a default empty Observable (or mock value)
    Object.defineProperty(target, propertyKey, {
      value: of(null),
      writable: true
    });
  })
}));

// Now when you import and instantiate your component, all @select properties will be mockable

This works with most Redux libraries that use class decorators for selectors—adjust the import path to match your library (e.g., @angular-redux/store).

3. Modify the Component Prototype

If the @select property is defined on the component’s prototype (common with some decorator implementations), you can set the mock value before creating the instance:

import { of } from 'rxjs';
import { MyComponent } from './my.component';
import { mockUser } from './mocks';

describe('MyComponent', () => {
  beforeEach(() => {
    // Set the mock Observable on the prototype
    MyComponent.prototype.user$ = of(mockUser);
  });

  it('should use the mocked user data', () => {
    const component = new MyComponent();
    // component.user$ will already be your mock Observable
    expect(component.user$).toBe(of(mockUser));
  });
});

All these approaches keep your tests focused on pure component logic without spinning up Angular’s testing module, which is exactly what you’re aiming for. Just adjust the syntax slightly based on the specific Redux library you’re using (decorator names, import paths, etc.).

内容的提问来源于stack exchange,提问作者Michael L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:47:24