I am making a very simple application which has one input box and a button.
Input is for entering email
Subscribe button with event handler
Entering email and click over the button will make an api call, (This method works)
subscribeEmail() {
this.error = '';
if (this.userForm.controls.email.status === 'VALID') {
const params = new HttpParams()
.set('EMAIL', this.userForm.controls.email.value)
.set('subscribe','Subscribe')
.set('b_aaa7182511d7bd278fb9d510d_01681f1b55','')
console.log(params);
const mailChimpUrl = this.mailChimpEndpoint + params.toString();
this.http.jsonp<MailChimpResponse>(mailChimpUrl, 'c').subscribe(response => {
console.log('response ', response)
if (response.result && response.result !== 'error') {
this.submitted = true;
}
else {
this.error = response.msg;
}
}, error => {
console.error(error);
this.error = 'Sorry, an error occurred.';
});
}
}
A complete working example here
There is no issues with it and you can also check everything works fine.
Requirement: I am in the need to cover test case for this button click and the http call with params.
I am unable to write the test case and it is showing that the tests are not covered for the http calls with params.
The tests that I have written so for for achieving the button click scenario like,
describe('HelloComponent', () => {
let component: HelloComponent;
let fixture: ComponentFixture<HelloComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
ReactiveFormsModule
],
declarations: [HelloComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HelloComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('check subscribeEmail function has value', (done: DoneFn) => {
const subscribeButton = fixture.debugElement.query(By.css('.subscribe'));
subscribeButton.triggerEventHandler('click', {});
done();
});
});
And the Working stackblitz with test cases here
(Please look into hello.component.spec.ts )
For button click, I have covered and it works
const subscribeButton = fixture.debugElement.query(By.css('.subscribe'));
subscribeButton.triggerEventHandler('click', {});
Could you please help me to achieve the result of covering the test case for the button click that has http call with params?
Update: After some search I have found that I can use httpmock to call the url with params but I am ending up with error as,
Error: Expected one matching request for criteria "Match URL: https://gmail.us10.list-manage.com/subscribe/post-json?u=aaa7182511d7bd278fb9d510d&id=01681f1b55&", found none.
You can also see the Modified stackblitz with httpMock here...
After all try only I am making this post so please consider this question and provide right solution.
A big thanks in advance.
That was a very long question, I understand that you have put a lot of time to create it. So, I have also put some time to refactor the code to make it as per the best practices. This would require to split your code as a service and make the code better for Unit Testing. (Unit testing for component & service)
MyService
and move thehttp
code into it. It would help you unit testcomponent
andservice
separately. I created as below:Create a Unit test for component as you can see here in the stackblitz . Take a good look at refactored code & how I have covered all cases depending on the scenario. As I have already explained in your previous question, you can test
MatSnackBar
callsSimilarly, you can write Unit test for service by referring to one my of my articles to test a service
Indeed it would be better to re-factory the code and make it more test friendly. But the provided example still could be covered with tests. The idea to verify the passed parameters and if parameters are correct then return a predictable response as an observable.
so, the this.http.jsonp returns the expected result only if passed parameters are correct.
Here you can find an working example
Please, noticed the I used some extra libs like jasmine-marbles to fake observables or moq.ts to mock HttpClient