I try to test a call to method inside on a subscriber, but I can't. Always that I call to method that has a subscribe, console send to me the error "Error: Expected spy saveMug to have been called". Also fail with reContent method.
My test should be isolated, so I can´t use fixture or testbed.
This is my component code
@Component({
selector: "app-mug",
templateUrl: "./mug.component.html",
styleUrls: ["./mug.component.scss"],
})
export class MugComponent implements OnInit
{
public mug: Mug= new Mug();
constructor(
public constants: Constants,
public mugService: mugService,
private messageService: MessageService,
public route: ActivatedRoute,
public router: Router,
) {
super(constants, route);
}
ngOnInit() {}
public saveMug(previous?: boolean): void {
const sub = this.mugService.saveMug(this.mug).subscribe((mug) => {
if (previous === undefined || previous === false) {
this.messageService.showMessage(
this.constants.MUG,
[this.constants.MUG_OK]
);
} else {
this.messageService.showMessage(
this.constants.MUG,
[this.constants.NO_MUG]
);
}
this.mug= new Mug(mug.dates);
});
this.subscriptions.add(sub);
}
}
This is my Spec.ts code
describe("MugComponent", () => {
let component;
const constants: Constants = new Constants();
let messageService= jasmine.createSpyObj("messageService", ["showMessage"]);
let route;
let router: Router;
beforeEach(() => {
component = new MugComponent(
constants,
messageService,
route,
router
);
component.mug= new Mug();
});
it("should call to showMessage", () => {
spyOn(component, "showMessage");
component.saveMug(true);
expect(component.showMessage).toHaveBeenCalled();
});
});
This is the Error
Error: Expected spy showMessage to have been called. at
Thanks.
CodePudding user response:
What is mugService
? How do you have access to it without injecting it in the constructor
?
That being said, I think you may need to use fakeAsync/tick
to make the subscription happen before your assertion.
In the component, I am going to assume there is a MugService
now.
constructor(
public constants: Constants,
private messageService: MessageService,
private mugService: MugService,
public route: ActivatedRoute,
public router: Router,
) {
super(constants, route);
}
let component;
const constants: Constants = new Constants();
let messageService= jasmine.createSpyObj("messageService", ["showMessage"]);
// !! create a spy
let mugService = jasmine.createSpyObj<MugService>("MugService", ['saveMug']);
let route;
let router: Router;
beforeEach(() => {
component = new MugComponent(
constants,
messageService,
// !! give spy object to component
mugService,
route,
router
);
component.mug= new Mug();
});
// !! wrap in fakeAsync
it("should call to showMessage", fakeAsync(() => {
// !! I don't think component.showMessage exists, messageService.showMessge does and it is already spied on
// !! make mugService.saveMug and return an observable
mugService.saveMug.and.returnValue(of({})); // you can mock what it returns however you wish
component.saveMug(true);
// !! wait for the subscription to complete
tick();
expect(messageService.showMessage).toHaveBeenCalled();
});
}));
CodePudding user response:
Well, I would suggest to let the mocked messageService's saveMenu
method return a value like of(new Mug())
.
I assume, the test case should validate, whether the messageService got called correctly after the component's saveMug
method was executed. This could be accomplished by doing something similar like:
describe("MugComponent", () => {
let component: MugComponent;
const constants: Constants = new Constants();
let route;
let router: Router;
let messageService= jasmine.createSpyObj("messageService", ["showMessage", "saveMenu"]);
messageService.saveMenu.and.returnValue(of(new Mug()));
beforeEach(() => {
component = new MugComponent(
constants,
messageService,
route,
router
);
component.mug = new Mug();
});
it("should call to showMessage", () => {
component.saveMug(true);
expect(messageService.showMessage).toHaveBeenCalled();
});
});