If I were looking to test the deals method in 'MyService' as detailed in your question, I would mock and spyon the two dependencies, as you mentioned, and then change the results from those dependencies and be sure all the test cases you want to account for are working. Since you don't have any error checking, I wouldn't test for that - though you do want to error check somewhere, perhaps in the services. I see at least three tests I would do: check the call and arguments sent to FirstService, check the call to SecondService, and check the return Observable.
I have set up a test stackblitz to demonstrate here: https://stackblitz.com/edit/stackoverflow-q-53102348?file=app%2Fmy.service.spec.ts
Here is the MyService describe from that stackblitz:
describe('MyService', () => {
let myService: MyService;
let mockFirstService = jasmine.createSpyObj('FirstService', {
post: of({results: 'Ok'})
});
let mockSecondService = jasmine.createSpyObj('SecondService', {
makeUrl: '/api/deals'
});
beforeEach(() => {
TestBed.configureTestingModule({
imports: [/* any imports needed */],
providers: [MyService,
{ provide: FirstService, useValue: mockFirstService },
{ provide: SecondService, useValue: mockSecondService }
]
});
myService = TestBed.get(MyService);
});
it('should be createable', () => {
expect(myService).toBeTruthy();
});
describe('deals() method', () => {
const testData: myModel = { meta: {}, data: 'test' };
it('should call secondService.makeUrl()', () => {
myService.deals(testData);
expect(mockSecondService.makeUrl).toHaveBeenCalled();
});
it('should call firstService.post() with an url and a myModel', () => {
myService.deals(testData);
expect(mockFirstService.post).toHaveBeenCalledWith('/api/deals', testData);
});
it('should return an Observable that resolves properly', () => {
mockFirstService.post.and.returnValue(of({results: 'Good'})); // Change return
myService.deals(testData).subscribe(data => {
expect(data).toEqual({results: 'Good'});
})
});
});
});