在Jasmine测试中使用toHaveBeenCalledWith时如何自定义匹配器?
Hey there! Great question—this is totally feasible, and there are a couple of clean ways to check that your service is sending the right Session header with your POST request. Let me walk you through them:
Option 1: Fit it directly into your existing expect statement
Since Angular uses an HttpHeaders object (not a plain JS object) for headers, we can't just use a simple objectContaining matcher. Instead, we can combine Jasmine's any matcher with a predicate to check the header value. Replace the ??? in your code with this:
jasmine.any(HttpHeaders) && jasmine.predicate((headers) => headers.get('Session') === 'abc')
This tells Jasmine to first verify that the headers are an instance of HttpHeaders, then check that calling get('Session') returns exactly abc.
Option 2: Break it down for readability
Sometimes, cramming all checks into one toHaveBeenCalledWith can get messy. A more straightforward approach is to grab the arguments from the spy call and check each part separately:
spyOn(http, 'post').and.returnValue(new Observable<Response>()); const result = service.Post<string>(data); assert.isNotNull(result); // Pull the options object from the most recent post call const [url, body, options] = http.post.calls.mostRecent().args; // Check the headers and observe option explicitly expect(options.observe).toBe('response'); expect(options.headers).toBeInstanceOf(HttpHeaders); expect(options.headers.get('Session')).toBe('abc');
This is often easier to debug if something goes wrong, since each assertion is separate and clearly states what you're checking.
Just don't forget to import HttpHeaders from @angular/common/http in your test file so the type checks work properly. Either approach will get the job done—pick whichever fits your test style better!
内容的提问来源于stack exchange,提问作者Stef Heyenrath

