You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
How to test an httpResource triggering an httpResource? #68808
I am trying to write a test case for when the result of an httpResource would trigger another httpResource, without having a component context (that is, when testing a service). For now I am failing to find a way to make the following test work:
Describe what you were looking for in the documentation
I was looking for details on how I can control the triggering of the loading of individual httpResources and waiting for them to load one by one.
Describe the actions that led you to experience the problem
Let's say I have an app that administers a catalog of dogs where the app on load would not only load the list of dogs but also automatically select the first dog and open its details. And once I added this automatic selection of the first dog with linkedSignal, my tests started breaking, even if the tests had nothing to do with checking the dog details.
Describe what you want to experience that would fix the problem
The documentation should tell more info about how we can resolve situations like this when there is a chain of httpResource requests where one triggers the other, so that the app can eventually become stable. As a follow-up problem, I should be able to be in control of whether my test wants the next request to be triggered.
Provide any additional information here in as much as detail as you can
My test code used Angular 20, but the problem is also reproducible with Angular 21.
This kind of selective waiting, I think, is what is missing from the documentation. Relying on await applicationRef.whenStable(); is not the most worthwhile method for complex applications, in my opinion. You might end up needing to mock more than you need. I think vi.waitUntil is a great way to do that, and it wasn't obvious to me that it works so well. Including this in the documentation as alternative would be great, IMO.
HttpTestingController vs. a declarative network fake such as MSW
Except for some very rare use cases, I would highly recommend to avoid using HttpTestingController.
Here is why:
IMO, its "imperative" API makes tests highly coupled to implementation details and encourages us to write over-specifying tests. In other words, in most cases, we want to test the behavior (i.e. fetching the right dog), not which http calls were made and in which order.
Even when we do not care about the order of the calls, it tends to force us to program each response in the right order.
If we cared about the order of the calls then, it would be much easier to assert the state of the signals and just check the requests "log" at the end if needed.
Its design encourages us to program a specific response for each request, instead of a behavior that mimics the server and that would be reusable across tests.
That's why, if you really need to "mock" at the HTTP level, I would highly recommend implementing a reusable fake.
A common alternative is MSW. This makes tests much more readable / maintainable / behavior-focused / cheaper to maintain.
In the Stackblitz, you can even see how to pause the details request so that you can test the state of the resources/signals or components when the resource is loading.
"Mocking" http vs. abstraction layer (this is more conceptual)
More generally speaking, I would recommend to avoid "mocking" at the HTTP level for the following reasons:
The HTTP API is an infrastructure implementation detail. The interface can change at any moment. The behavior too. Something has to make sure that the mocks behave like the real API.
It couples tests to the infrastructure. (Ex. when the types changes, this will affect many tests).
As consumers of an HTTP API, we do not necessarily have the expertise of its behavior. (Ex. what happens when I add 10 dogs, does it return a 403 because I have to pay first before adding more dogs there?)
It is better to provide fakes at an abstraction layer with core types that you totally control.
For example, a DogRepositoryFake service that creates Angular resources with in memory data with your types.
The real implementation can use httpResource.
The problem then is how do you make sure the real implementation works.
Well it can be in the happy path of wider tests such as end-to-end, or through contract tests. A test that runs on both the fake implementation and against the real backend to make sure that they behave the same.
Here is an example of this: https://github.com/yjaaidi/kitchen/tree/ashes-to-ashes-specs-to-specs/apps/whiskmate/src/app/recipe/recipe-repository
In the meantime, I adopted MSW in my project. I know it's not exactly what you suggested as most ideal, but it's a step forward, as I got a much cleaner testing setup:
I could increase my coverage because I didn't have to mock service classes.
I used to have chicken-and-egg problems with the HTTP testing controller, because the render function I used for Vitest browser mode sometimes happened to render a component that made a HTTP request on first render, before I could inject the HTTP testing controller to expect requests before they are made. Because of this, I needed to mock the httpResource object, which was ugly.
The details of my challenges are in this commit in case it's needed for anyone for some reason (also check the removed code then): rkrisztian/contenttree@7d56ac5
However, it wasn't without further challenges. Currently MSW does not load successfully out of the box in Vitest, which is tracked in an issue: angular/angular-cli#32523
But at least I found a workaround.
As for mocking on abstraction layer: could work too, but I'm afraid I would only repeat my previous struggles with the httpResource mocking, like losing coverage percentage, or not testing exactly what actually the app does. Signals are so behavior-defining features that if I my mocks didn't exactly follow how the app actually worked, I could have realisticity issues either breaking tests or giving me false positive results. Which means that my tests were duplicating implementation details.
=> So all in all, I think MSW is currently the biggest win here.
Activity
JeanMeche commentedon May 20, 2026
You can't really on stability here because of the interlocking it causes (the first resource resolving, triggers the other resource).
The best alternative is to wait/poll for the resource value.
For example with vitest:
rkrisztian commentedon May 20, 2026
Accidentally closed. Sorry, I'm still elaborating my response.
rkrisztian commentedon May 20, 2026
Thank you, @JeanMeche, your solution works very well. It can also be used to wait for
httpResources:Both will trigger the HTTP request for the
selectedDogDetails, which then can now be mocked.I created an Angular 21 + Vitest-based example to update my example code:
https://stackblitz.com/edit/angular-vitest-starter-v21-gx9buvbk?file=src%2Fexample.spec.ts
This kind of selective waiting, I think, is what is missing from the documentation. Relying on
await applicationRef.whenStable();is not the most worthwhile method for complex applications, in my opinion. You might end up needing to mock more than you need. I thinkvi.waitUntilis a great way to do that, and it wasn't obvious to me that it works so well. Including this in the documentation as alternative would be great, IMO.JeanMeche commentedon May 20, 2026
Thank you for your feedback. We indeed plan to rewamp our testing docs and include more pragmatic testing examples.
yjaaidi commentedon May 20, 2026
Hi @rkrisztian, indeed, in most cases, polling is the way to go.
expect.poll+ waiting for http requestBy the way, you can simplify the tests a little more using
expect.polland also by waiting for the HTTP request to happen instead. See https://stackblitz.com/edit/angular-vitest-test-example-for-chaining-http-resource?file=src%2Fexample.spec.tsand
HttpTestingControllervs. a declarative network fake such as MSWExcept for some very rare use cases, I would highly recommend to avoid using
HttpTestingController.Here is why:
That's why, if you really need to "mock" at the HTTP level, I would highly recommend implementing a reusable fake.
A common alternative is MSW. This makes tests much more readable / maintainable / behavior-focused / cheaper to maintain.
See https://stackblitz.com/edit/mocking-network-with-angular-vitest-msw?file=src%2Fdog-store.spec.ts
The tests looks like this (and the whole thing is more type-safe):
and the reusable MSW fake looks like this:
In the Stackblitz, you can even see how to pause the details request so that you can test the state of the resources/signals or components when the resource is loading.
"Mocking" http vs. abstraction layer (this is more conceptual)
More generally speaking, I would recommend to avoid "mocking" at the HTTP level for the following reasons:
It is better to provide fakes at an abstraction layer with core types that you totally control.
For example, a
DogRepositoryFakeservice that creates Angular resources with in memory data with your types.The real implementation can use
httpResource.The problem then is how do you make sure the real implementation works.
Well it can be in the happy path of wider tests such as end-to-end, or through contract tests. A test that runs on both the fake implementation and against the real backend to make sure that they behave the same.
Here is an example of this: https://github.com/yjaaidi/kitchen/tree/ashes-to-ashes-specs-to-specs/apps/whiskmate/src/app/recipe/recipe-repository
Sorry for the shameless plug, but if you want to dive deeper into this, you can read this: https://cookbook.marmicode.io/angular/testing/fake-it-till-you-mock-it
I hope this helps.
rkrisztian commentedon May 21, 2026
@yjaaidi, thank you, I'm going to need time to process all the information, but very cool!
rkrisztian commentedon Jun 10, 2026
In the meantime, I adopted MSW in my project. I know it's not exactly what you suggested as most ideal, but it's a step forward, as I got a much cleaner testing setup:
renderfunction I used for Vitest browser mode sometimes happened to render a component that made a HTTP request on first render, before I could inject the HTTP testing controller to expect requests before they are made. Because of this, I needed to mock thehttpResourceobject, which was ugly.The details of my challenges are in this commit in case it's needed for anyone for some reason (also check the removed code then):
rkrisztian/contenttree@7d56ac5
However, it wasn't without further challenges. Currently MSW does not load successfully out of the box in Vitest, which is tracked in an issue:
angular/angular-cli#32523
But at least I found a workaround.
As for mocking on abstraction layer: could work too, but I'm afraid I would only repeat my previous struggles with the
httpResourcemocking, like losing coverage percentage, or not testing exactly what actually the app does. Signals are so behavior-defining features that if I my mocks didn't exactly follow how the app actually worked, I could have realisticity issues either breaking tests or giving me false positive results. Which means that my tests were duplicating implementation details.=> So all in all, I think MSW is currently the biggest win here.