Mock an Angular Service to return a different response
craigbroadman opened this issue · 2 comments
Versions
6.1.2
Repro steps
- I have an Angular Component using ngOnInit - this calls an Angular Service that in turn makes a Http Call to update a user record in the database
- The Service a further 9 functions to do different things
- The API has all the information it needs in Claims, there are therefore no parameters passed to the Angular Service and no parameters passed to the API
- The API call could return 3 potential responses (A, B, C)
- The UI Component behaves differently depending on the response.
Observed Behavior
<!-- Normally this includes a stack trace and some more information -->
I have created a sandbox file for the given component and created a mock of the service and it's 10 functions.
I have hard coded the function that can return 3 different responses to return response "A".
I have setup a scenario for response A and all is working fine.
Desired Behavior
<!--
What do you expect to see?
-->
What I would like to be able to do is write scenario B and C without having to write different versions of the mocked service. Is this possible? If so, what is the best approach?
Any other details that may be useful (optional)
Here is an example of the service
`
export class IdentityService {
constructor(private http: HttpClient) { }
public createIdentity(): Observable<CreateIdentityResponseDto> {
return this.http.post<CreateIdentityResponseDto>('identity', null);
}
public updateIdentity(): Observable<UpdateIdentityResponseDto> {
// Can return response A, B or C
return this.http.put<UpdateIdentityResponseDto>('identity', null);
}
public getResendActivationEmailThrottlingSettings(): Observable<ResendActivationEmailSettingsDto> {
return this.http.get<ResendActivationEmailSettingsDto>('activation/resend-activation-email-settings');
}
public resendActivationEmail(ResendActivationEmailRequestDto): Observable<ResendActivationEmailResponseDto> {
return this.http.put<ResendActivationEmailResponseDto>('activation/resend-activation-email', ResendActivationEmailRequestDto);
}
public resendEmailAddressChangeEmail(): Observable<ResendEmailAddressChangeResponseDto> {
return this.http.put<ResendEmailAddressChangeResponseDto>('identity/email-address-change-resend', null);
}
public getResendEmailAddressChangeThrottlingSettings(): Observable<ResendEmailAddressChangeSettingsResponseDto> {
return this.http.get<ResendEmailAddressChangeSettingsResponseDto>('identity/resend-email-address-change-settings');
}
public getIdentityDetails(): Observable<GetUserDetailsResponseDto> {
return this.http.get<GetUserDetailsResponseDto>('identity/user-details');
}
}
Mock Service
class MockIdentityService {
updateIdentity(): Observable<UpdateIdentityResponseDto> {
var result: UpdateIdentityResponseDto = {
responseType: 'A'
};
return of(result);
}
getIdentityDetails(): Observable<GetUserDetailsResponseDto> {
var result: GetUserDetailsResponseDto = {
emailAddress: 'sandbox@ipipeline.com',
authenticationType: 'LDAP'
};
return of(result);
}
getResendActivationEmailThrottlingSettings(): Observable<ResendActivationEmailSettingsDto> {
var result: ResendActivationEmailSettingsDto = {
resendActivationEmailThrottledInMinutes: 1,
disableResendEmailInMilliseconds: 1000
};
return of(result);
}
getResendEmailAddressChangeThrottlingSettings(): Observable<ResendEmailAddressChangeSettingsResponseDto> {
var result: ResendEmailAddressChangeSettingsResponseDto = {
resendEmailAddressChangeThrottledInMinutes: 1,
disableResendEmailInMilliseconds: 1000
};
return of(result);
}
resendActivationEmail(resendActivationEmailRequestDto): Observable<ResendActivationEmailResponseDto> {
var result: ResendActivationEmailResponseDto = {
errorMessage: '',
isSuccessful: true,
disableResendEmailInMilliseconds: 1000
};
return of(result);
}
};
The only way I can think of to accomplish what you are trying to do is to provide a different mock service for each scenario. You could use the same mock service wrapping it in a factory method that could return a different result in each scenario. That way you only have to have a single mock service.
Mock Service:
class MockIdentityService {
constructor(private response: string) {}
updateIdentity(): Observable<UpdateIdentityResponseDto> {
var result: UpdateIdentityResponseDto = {
responseType: this.response
};
return of(result);
}
...
}
Sandbox Example:
export default sandboxOf(IdentityComponent)
.add('identity service returns A', {
template: `<app-identity></app-identity>`,
providers: [
{provide: IdentityService, useFactory: () => new MockIdentityService('A')}
]
})
.add('identity service returns B', {
template: `<app-identity></app-identity>`,
providers: [
{provide: IdentityService, useFactory: () => new MockIdentityService('B')}
]
});
Perfect, that's a great option. Thanks