Angular 角度单元测试用例中的错误:TypeError:this.userService.currentUser.subscribe不是函数

Angular 角度单元测试用例中的错误:TypeError:this.userService.currentUser.subscribe不是函数,angular,jasmine,karma-jasmine,angular-test,Angular,Jasmine,Karma Jasmine,Angular Test,我在运行angular单元测试用例时遇到此错误: 测试结果 SidebarComponent × should create TypeError: this.userService.currentUser.subscribe is not a function 侧栏组件规格ts describe('SidebarComponent', () => { let fixture: ComponentFixture<SidebarComponent>; let

我在运行angular单元测试用例时遇到此错误:

测试结果

SidebarComponent
   × should create
    TypeError: this.userService.currentUser.subscribe is not a function
侧栏组件规格ts

describe('SidebarComponent', () => {
  let fixture: ComponentFixture<SidebarComponent>;
  let mockUserService;

  beforeEach(() => {
    mockUserService = jasmine.createSpyObj(['currentUser']);

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [SidebarComponent],
      schemas: [NO_ERRORS_SCHEMA],
      providers: [{ provide: UserService, useValue: mockUserService }]
    });

    fixture = TestBed.createComponent(SidebarComponent);
  });

  fit('should create', () => {
    mockUserService.currentUser.and.returnValue(of('Here goes an object'));
    fixture.detectChanges();
    expect(SidebarComponent).toBeTruthy();
  });
});
ngOnInit() {
    this.userService.currentUser.subscribe(currentUser => {
        // Some code here
    });
}
@Injectable({ providedIn: 'root'})
export class UserService {
  private currentUserSubject = new BehaviorSubject({});
  public currentUser: Observable<User> = this.currentUserSubject.asObservable().pipe(distinctUntilChanged());

  setUser(user) {
      this.currentUserSubject.next({ ...newUser });
  }
}
describe('SidebarComponent', () => {
  let component: SidebarComponent;
  let fixture: ComponentFixture<SidebarComponent>;
  let userService: UserService;

  beforeEach(done => {
    TestBed.configureTestingModule({
    imports: [HttpClientTestingModule, RouterTestingModule],
    declarations: [SidebarComponent],
    schemas: [NO_ERRORS_SCHEMA]
  })
  .compileComponents()
  .then(() => {
    fixture = TestBed.createComponent(SidebarComponent);
    component = fixture.componentInstance;

    userService = TestBed.get(UserService);
    userService.setUser(userInfo);

    fixture.detectChanges();
    done();
  });
 });

 it('should create', done => {
   expect(component).toBeTruthy();
   done();
 });
})
package.json

"devDependencies": {
    "@types/jasmine": "2.8.8",
    "@types/jasminewd2": "2.0.3",
    "@types/node": "9.6.23",
    "jasmine-core": "2.99.1",
    "jasmine-spec-reporter": "4.2.1",
    "karma": "4.2.0",
    "karma-chrome-launcher": "2.2.0",
    "karma-cli": "2.0.0",
    "karma-coverage-istanbul-reporter": "1.4.3",
    "karma-jasmine": "2.0.1",
    "karma-jasmine-html-reporter": "1.4.0",
    "karma-junit-reporter": "1.2.0",
    "karma-spec-reporter": "0.0.32",
    "protractor": "6.0.0",
    "rxjs-tslint": "0.1.7",
}
user.service.ts

describe('SidebarComponent', () => {
  let fixture: ComponentFixture<SidebarComponent>;
  let mockUserService;

  beforeEach(() => {
    mockUserService = jasmine.createSpyObj(['currentUser']);

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [SidebarComponent],
      schemas: [NO_ERRORS_SCHEMA],
      providers: [{ provide: UserService, useValue: mockUserService }]
    });

    fixture = TestBed.createComponent(SidebarComponent);
  });

  fit('should create', () => {
    mockUserService.currentUser.and.returnValue(of('Here goes an object'));
    fixture.detectChanges();
    expect(SidebarComponent).toBeTruthy();
  });
});
ngOnInit() {
    this.userService.currentUser.subscribe(currentUser => {
        // Some code here
    });
}
@Injectable({ providedIn: 'root'})
export class UserService {
  private currentUserSubject = new BehaviorSubject({});
  public currentUser: Observable<User> = this.currentUserSubject.asObservable().pipe(distinctUntilChanged());

  setUser(user) {
      this.currentUserSubject.next({ ...newUser });
  }
}
describe('SidebarComponent', () => {
  let component: SidebarComponent;
  let fixture: ComponentFixture<SidebarComponent>;
  let userService: UserService;

  beforeEach(done => {
    TestBed.configureTestingModule({
    imports: [HttpClientTestingModule, RouterTestingModule],
    declarations: [SidebarComponent],
    schemas: [NO_ERRORS_SCHEMA]
  })
  .compileComponents()
  .then(() => {
    fixture = TestBed.createComponent(SidebarComponent);
    component = fixture.componentInstance;

    userService = TestBed.get(UserService);
    userService.setUser(userInfo);

    fixture.detectChanges();
    done();
  });
 });

 it('should create', done => {
   expect(component).toBeTruthy();
   done();
 });
})
@Injectable({providedIn:'root'})
导出类用户服务{
private currentUserSubject=new BehaviorSubject({});
public currentUser:Observable=this.currentUserSubject.asObservable().pipe(distinctUntilChanged());
设置用户(用户){
this.currentUserSubject.next({…newUser});
}
}
据我所知,要解决这个问题,我们需要在以下声明中使用:

mockUserService.currentUser.and.returnValue(of('heregoeanobject')

其中of是从“rxjs”导入的。当我记录of的值(“对象出现了”)时,它表明它是可观察的


我如何解决这个问题?

你可以这样模仿:

export const mockUserService= {
    currentUser = {
        subscribe() {
          return of({ 
              // whatever here
          });
        }
    }
};

代码创建了一个假的服务。此假服务您可以添加被测试组件使用的所有功能和成员。

使用
spyOn
模拟特定服务方法如何:

const userService = TestBed.get(UserService);
const mockedResponse = {}; // Modify as per your need
spyOn(userService, 'currentUser').and.callFake(() => {
  return of(mockedResponse);
});

这对我有用

在做了一些测试之后,我发现我们不能使用spyOn(userService,'currentUser')。原因很清楚,currentUser不是一个函数,而是一个变量,我们在其中分配了一个可观察变量。SpyOn会在上面创建一个假函数,但我们需要的是一个可观察的。因此,我们可以使用userService.setUser方法来适当地设置currentUser的值

侧栏组件规格ts

describe('SidebarComponent', () => {
  let fixture: ComponentFixture<SidebarComponent>;
  let mockUserService;

  beforeEach(() => {
    mockUserService = jasmine.createSpyObj(['currentUser']);

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [SidebarComponent],
      schemas: [NO_ERRORS_SCHEMA],
      providers: [{ provide: UserService, useValue: mockUserService }]
    });

    fixture = TestBed.createComponent(SidebarComponent);
  });

  fit('should create', () => {
    mockUserService.currentUser.and.returnValue(of('Here goes an object'));
    fixture.detectChanges();
    expect(SidebarComponent).toBeTruthy();
  });
});
ngOnInit() {
    this.userService.currentUser.subscribe(currentUser => {
        // Some code here
    });
}
@Injectable({ providedIn: 'root'})
export class UserService {
  private currentUserSubject = new BehaviorSubject({});
  public currentUser: Observable<User> = this.currentUserSubject.asObservable().pipe(distinctUntilChanged());

  setUser(user) {
      this.currentUserSubject.next({ ...newUser });
  }
}
describe('SidebarComponent', () => {
  let component: SidebarComponent;
  let fixture: ComponentFixture<SidebarComponent>;
  let userService: UserService;

  beforeEach(done => {
    TestBed.configureTestingModule({
    imports: [HttpClientTestingModule, RouterTestingModule],
    declarations: [SidebarComponent],
    schemas: [NO_ERRORS_SCHEMA]
  })
  .compileComponents()
  .then(() => {
    fixture = TestBed.createComponent(SidebarComponent);
    component = fixture.componentInstance;

    userService = TestBed.get(UserService);
    userService.setUser(userInfo);

    fixture.detectChanges();
    done();
  });
 });

 it('should create', done => {
   expect(component).toBeTruthy();
   done();
 });
})
description('SidebarComponent',()=>{
let组件:侧边栏组件;
let夹具:组件夹具;
让userService:userService;
每次之前(完成=>{
TestBed.configureTestingModule({
导入:[HttpClientTestingModule,RouterTestingModule],
声明:[侧边栏组件],
架构:[无错误\u架构]
})
.compileComponents()
.然后(()=>{
fixture=TestBed.createComponent(SidebarComponent);
组件=fixture.componentInstance;
userService=TestBed.get(userService);
setUser(userInfo);
fixture.detectChanges();
完成();
});
});
它('should create',done=>{
expect(component.toBeTruthy();
完成();
});
})

你能把问题中添加的
userService
代码贴在这里吗?为什么我们不能用下面的方法?mockUserService=jasmine.createSpyObj(['currentUser']);我知道我可以编写完整的模拟服务,但这对我来说没有必要增加代码,因为要模拟的服务太多了。不确定。。。也许这也能起作用:jasmine.createSpyObj([{currentUser={subscribe(){…}]);