Skip to content
tezvyn:

Top 30 Dependency Injection Interview Questions and Answers

30 multiple-choice questions on Dependency Injection, drawn from 30 bites out of the 39 tagged Dependency Injection on Tezvyn. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    Why does Angular treat dependency injection as a runtime architectural layer rather than relying on ES module imports like Vue?

    Show the answer

    Answer: c · It enables runtime resolution of service lifetimes and implementation swapping without changing consumer code or direct file coupling.

    Angular's DI is a runtime inversion-of-control system that supports scoped lifetimes, tree-shakable providers, and test-time substitution without modifying consumer code. The boilerplate distractor is wrong because DI still requires constructor declarations; its architectural value lies in runtime indirection and hierarchical resolution, not syntax savings.

    Read the full bite: Why is DI central to Angular architecture versus Vue's module system?

  2. Question 2 of 30

    In FastAPI, why should an async database session dependency wrap yield in try and place await session.close() in finally?

    Show the answer

    Answer: a · It guarantees cleanup runs even if the path operation raises an exception.

    A try/finally block guarantees that await session.close() runs even when the path operation raises an exception, preventing database connection leaks. The thread pool issue in distractor C is caused by using def instead of async def, not by omitting exception handling.

    Read the full bite: Implement an async database session dependency using yield for setup and teardown

  3. Question 3 of 30

    An abstract domain package and a concrete storage package import each other. Which refactor best restores clean architecture?

    Show the answer

    Answer: d · Define a storage interface in the domain layer and inject the concrete implementation at startup

    Defining the interface in the domain layer and injecting the concrete implementation at startup inverts the dependency, which is the recommended pattern for layer violations. Merging is better reserved for packages with no clear hierarchy, and build tags are a red-flag workaround that avoids fixing the design.

    Read the full bite: Why does Go forbid circular dependencies, and how do you resolve them?

  4. Question 4 of 30

    In FastAPI, which approach best implements a reusable current-user check that preserves OpenAPI docs integration and keeps endpoints testable?

    Show the answer

    Answer: a · Define a get_current_user dependency that uses OAuth2PasswordBearer, validates the token, returns a User model, and inject it into routes with Depends.

    A dedicated get_current_user dependency keeps auth explicit in the signature, auto-documents security in OpenAPI, and enables test overrides via app.dependency_overrides. Middleware hides the dependency from the docs and complicates testing.

    Read the full bite: How do you create a reusable current-user dependency in FastAPI?

  5. Question 5 of 30

    What is the main reason to declare a FastAPI dependency in a path operation parameter?

    Show the answer

    Answer: a · To let FastAPI automatically inject reusable logic so routes stay focused on HTTP concerns.

    The correct answer is C because dependency injection allows FastAPI to wire reusable components into routes, keeping handlers clean. A is tempting because it describes calling helpers, but that misses the inversion-of-control pattern where the framework injects the dependency rather than the route calling it manually.

    Read the full bite: How do you declare a function as a dependency, and why?

  6. Question 6 of 30

    Which is the correct way to apply a shared dependency to every route in an APIRouter without adding it to each endpoint signature?

    Show the answer

    Answer: d · Pass a list of Depends() instances to the dependencies parameter when creating the APIRouter

    APIRouter's dependencies parameter automatically injects shared dependencies into every mounted route while keeping endpoint signatures clean and preserving OpenAPI docs. Middleware runs globally on all requests rather than being router-scoped, and custom decorators break FastAPI's automatic schema generation.

    Read the full bite: How do you apply a dependency to an APIRouter without per-endpoint signatures?

  7. Question 7 of 30

    When you assign a mock to app.dependency_overrides[get_db] in FastAPI, what happens during the test and what must you do afterward?

    Show the answer

    Answer: b · FastAPI injects the mock exclusively, bypassing the original and its sub-dependencies, and you must manually clear overrides after the test.

    FastAPI uses the replacement function exclusively and never executes the original dependency or its sub-dependencies. Option C is tempting but incorrect because sub-dependencies are fully bypassed, not preserved, and overrides persist until you manually clear them.

    Read the full bite: How would you override a FastAPI dependency during testing?

  8. Question 8 of 30

    You need a FastAPI dependency that accepts roles in its constructor and validates the current user each request. Why use a callable class rather than a plain function?

    Show the answer

    Answer: b · The class __init__ receives configuration and sub-dependencies declaratively while __call__ handles per-request logic and OpenAPI integration

    A callable class lets FastAPI resolve constructor sub-dependencies and configuration via __init__ while __call__ handles per-request execution and remains visible to OpenAPI. The tempting distractor wrongly claims you must manually instantiate the class inside the endpoint, which defeats automatic injection and is explicitly flagged as a red flag.

    Read the full bite: How do you use a Python class as a FastAPI dependency?

  9. Question 9 of 30

    In FastAPI, a database-querying dependency is injected into both a path operation and a sub-dependency. By default, what happens during a single request?

    Show the answer

    Answer: c · The dependency runs once and the cached value is reused only within that request's dependency tree

    FastAPI defaults to use_cache=True, so it executes the dependency once per request and reuses that cached value throughout the same request's dependency tree. Option A is a common misconception: FastAPI does not independently resolve every Depends() declaration; it avoids redundant work by caching within the request lifecycle.

    Read the full bite: How does FastAPI cache dependencies within a single request?

  10. Question 10 of 30

    You need a FastAPI dependency that combines a path parameter and a request header. What is the correct implementation pattern?

    Show the answer

    Answer: d · Annotate each parameter in the dependency function with its source (e.g., Path, Header) and declare the function as a dependency with Depends().

    FastAPI inspects dependency signatures using the same resolution engine as endpoints, so annotating parameters with Path, Header, or similar and using Depends() lets the framework inject them automatically. Option B is tempting for developers familiar with lower-level frameworks, but manually parsing Request bypasses validation and defeats the purpose of FastAPI's dependency injection system.

    Read the full bite: How would you implement a dependency requiring multi-source parameters?

  11. Question 11 of 30

    You move a dependency that loads a 2GB ML model from a global FastAPI app dependency to a single path operation. What is the actual effect?

    Show the answer

    Answer: d · It runs only when that specific path is hit, yet still reloads the model on every request to that path.

    Path-local dependencies are resolved per-request, so the expensive load repeats on every call to that route; moving it merely limits blast radius. Distractor D is wrong because limiting the dependency to one route does not eliminate per-request overhead, which is why expensive initialization belongs in a lifespan event or cached singleton.

    Read the full bite: How does lifecycle differ for global vs path operation dependencies?

  12. Question 12 of 30

    In FastAPI, when a dependency callable declares its own parameters using Depends, how does the framework resolve them at runtime?

    Show the answer

    Answer: d · It builds a dependency graph, resolving sub-dependencies first and injecting their results into parent dependencies.

    FastAPI's injection solver treats Depends declarations as nodes in a dependency graph, recursively resolving sub-dependencies and feeding their outputs into parent callables before the endpoint executes. This is fundamentally different from middleware, which intercepts requests at the ASGI layer rather than performing parameter-level resolution.

    Read the full bite: Explain the internal role of the Depends class

  13. Question 13 of 30

    You need to enforce authentication on every /users endpoint while leaving /items public. What is the most maintainable FastAPI approach?

    Show the answer

    Answer: c · Pass dependencies=[Depends(get_current_user)] to the users APIRouter and omit it from the items router, then include both in the app.

    Passing dependencies to APIRouter scopes authentication to that router only while keeping other routers unaffected and preserving OpenAPI docs. Adding Depends to every route manually violates DRY and makes refactoring painful, even though it produces the same runtime behavior.

    Read the full bite: How to apply a dependency to only one FastAPI router?

  14. Question 14 of 30

    When scaling FastAPI beyond simple routes, what is the recommended pattern for combining framework-native Depends with a formal DI container?

    Show the answer

    Answer: a · Bootstrap a container during startup for singletons and deep graphs, then use thin Depends wrappers to resolve or build request-scoped services.

    The card recommends a hybrid approach: a formal container initializes singletons and deep graphs during startup, while thin Depends callables bridge request-scoped resources into FastAPI. Option C is the red flag of using Depends for everything, which scatters construction logic and hurts testability, while C creates noisy transitive coupling in routes and D sacrifices explicit lifecycle management.

    Read the full bite: How do you manage service lifecycle with FastAPI Depends versus formal DI?

  15. Question 15 of 30

    How do you override a dependency for a single APIRouter without affecting the main FastAPI application?

    Show the answer

    Answer: b · Instantiate a sub-application, set its dependency_overrides, include the router, and mount it in the main app

    Only FastAPI application instances maintain a dependency_overrides dictionary; APIRouter is merely a route grouping mechanism with no such registry. Mounting a sub-application with its own overrides isolates the mock without leaking state into the main app or relying on fragile global mutations.

    Read the full bite: Override a FastAPI dependency at the APIRouter level

  16. Question 16 of 30

    What is the most accurate description of how the Provider package relates to InheritedWidget?

    Show the answer

    Answer: d · Provider is a wrapper over InheritedWidget that adds lifecycle and ergonomics

    Provider builds directly on InheritedWidget, adding boilerplate reduction, disposal, and scoped reads. It is not an independent store, so the reactive-store option is a common misconception.

    Read the full bite: Provider package versus raw InheritedWidget

  17. Question 17 of 30

    What is the primary reason to use FastAPI's Security() utility instead of Depends() for authentication?

    Show the answer

    Answer: a · It signals to OpenAPI that a dependency is a security requirement, enabling interactive documentation.

    The card emphasizes that the key distinction of Security() is its role in signaling security requirements to OpenAPI, which enables interactive documentation features like lock icons and 'Authorize' buttons. While Security() does work with functions that raise HTTPExceptions for authentication failures, standard Depends() can also be used with such functions, making the OpenAPI integration the primary differentiator.

    Read the full bite: FastAPI's Security Utility: Dependencies for Auth

  18. Question 18 of 30

    For which task would a developer most appropriately access the raw Request object in a FastAPI endpoint?

    Show the answer

    Answer: d · Retrieving the client's IP address for logging purposes.

    The card explicitly states that retrieving the client's IP address is a common and appropriate use case for accessing the raw Request object. Using the raw Request object for standard tasks like extracting query parameters or validating Pydantic models bypasses FastAPI's declarative syntax, validation, and documentation features, which is advised against.

    Read the full bite: Accessing the Raw Request Object in FastAPI

  19. Question 19 of 30

    In a large multi-module Android codebase, which pattern correctly implements inversion of control for cross-feature navigation without violating the dependency rule?

    Show the answer

    Answer: b · Use a shared navigation contract module for route definitions, with each feature contributing handlers to a DI multibinding map resolved by the app module.

    B correctly applies inversion of control by isolating features behind a contract module and delegating wiring to the app module via dependency injection. C is tempting but wrong because a monolithic common module still implicitly couples features and becomes an unmaintainable dumping ground.

    Read the full bite: How do you navigate between feature modules without direct dependencies?

  20. Question 20 of 30

    Which pattern correctly wires SQLAlchemy from configuration to endpoint in FastAPI without risking connection leaks?

    Show the answer

    Answer: d · Define a module-level engine and sessionmaker, then yield request-scoped sessions in a dependency with cleanup in a finally block.

    Option D is correct because a single engine manages the connection pool globally, and yielding sessions with a finally block ensures each request gets its own safely closed session. Option A is tempting but wrong because creating an engine per request is expensive and defeats connection pooling, quickly exhausting database resources.

    Read the full bite: Describe SQLAlchemy setup in FastAPI from database config to endpoint

  21. Question 21 of 30

    Why should get_db use yield instead of return when providing a database session to FastAPI endpoints?

    Show the answer

    Answer: d · Yield ensures cleanup logic in the finally block runs after the endpoint completes.

    Using yield with a finally block guarantees the session closes after the endpoint runs, even if an exception occurs. Reusing a cached session across requests, as in option C, breaks thread safety and causes concurrency issues.

    Read the full bite: How do you use FastAPI dependency injection for database sessions?

  22. Question 22 of 30

    What does FastAPI automatically do when you inject an OAuth2PasswordBearer instance into an endpoint using Depends?

    Show the answer

    Answer: c · Expect a Bearer token in the Authorization header, return 401 if absent, and add security metadata to OpenAPI docs

    Injecting OAuth2PasswordBearer via Depends tells FastAPI to require an Authorization: Bearer header, automatically return 401 if it is missing, and document the requirement in OpenAPI. Option D is tempting but wrong because the scheme itself does not query a database or return a user object; that requires a separate custom dependency.

    Read the full bite: How do you protect a FastAPI endpoint using Depends and OAuth2PasswordBearer?

  23. Question 23 of 30

    When implementing JWT-based RBAC in FastAPI, how should you handle a request with a valid token but an insufficient role claim?

    Show the answer

    Answer: b · Use a parameterized dependency that depends on a base JWT decoder and raises 403 Forbidden

    A parameterized dependency composed on a base JWT decoder keeps routes clean and correctly raises 403 because the token is valid but the user lacks permission. Returning 401 is wrong for valid tokens, and querying a database or hardcoding 'admin' violates the pattern of extracting roles from JWT claims.

    Read the full bite: Implement RBAC in FastAPI with a JWT role dependency

  24. Question 24 of 30

    What is the main architectural benefit of using Hilt over manual dependency instantiation in Android?

    Show the answer

    Answer: c · It automates object graph construction and lifecycle-aware scoping at compile time

    Hilt generates the object graph at compile time and manages lifecycle-aware scopes, so consumers receive dependencies without knowing how to construct them. Distractor B is wrong because Hilt uses compile-time annotation processing and code generation, not runtime reflection.

    Read the full bite: What is Dependency Injection and Hilt's benefit over manual instantiation?

  25. Question 25 of 30

    You control the UserRepository source code and need to inject it into a HiltViewModel. Which approach follows Hilt best practices?

    Show the answer

    Answer: d · Annotate UserRepository's constructor with @Inject and declare it in the ViewModel's constructor; no module is needed for UserRepository.

    Annotating UserRepository's constructor with @Inject lets Hilt automatically provide it to the ViewModel without a module because you control the source. Writing a @Provides module for a class you own is tempting but wrong because it adds unnecessary boilerplate and hides the graph from compile-time validation.

    Read the full bite: How do you inject UserRepository into a ViewModel with Hilt?

  26. Question 26 of 30

    How does the lifecycle of an @ActivityRetainedScoped dependency differ from a @Singleton dependency in Hilt?

    Show the answer

    Answer: a · @Singleton lives for the app process, while @ActivityRetainedScoped survives config changes but dies when the activity finishes.

    @Singleton is tied to the application process via SingletonComponent, whereas @ActivityRetainedScoped is retained across configuration changes by ActivityRetainedComponent but destroyed when the activity finishes. Option C is tempting because both scopes do outlive a single Activity instance, but they differ fundamentally in scope and lifecycle ownership.

    Read the full bite: Explain Hilt scoping: @Singleton vs @ActivityRetainedScoped

  27. Question 27 of 30

    You need to inject both a logging and a plain OkHttpClient using Hilt. Which pattern best disambiguates the bindings without leaking creation details into consumers?

    Show the answer

    Answer: c · Define a custom @Qualifier, annotate two @Provides methods in a @Module, and annotate the injection sites

    Custom qualifiers are the type-safe, idiomatic way to distinguish multiple bindings of the same type while keeping construction logic inside the module. Subclassing OkHttpClient and using @Binds is a common anti-pattern because @Binds cannot run builder configuration like addInterceptor, and wrapper types pollute the domain model.

    Read the full bite: How do you inject two different OkHttpClient instances with Hilt?

  28. Question 28 of 30

    Why inject the NetworkService as a protocol rather than constructing it inside the ViewModel?

    Show the answer

    Answer: b · It lets tests substitute a mock so behaviour is deterministic and offline

    Protocol injection lets the test pass a controllable mock, keeping the test fast, offline, and deterministic. Binary size and runtime speed are unrelated, and XCTest imposes no such requirement.

    Read the full bite: Unit test a ViewModel with a mocked NetworkService

  29. Question 29 of 30

    Your teammate binds an interface to its @Inject-annotated implementation using @Provides in a concrete module. What is the main drawback compared to using @Binds?

    Show the answer

    Answer: c · It adds unnecessary overhead by generating a factory even though Dagger already knows how to construct the type

    @Provides generates an intermediate factory even when the implementation already has an @Inject constructor, whereas @Binds links the interface to that implementation without extra generated code. Option A is wrong because @Provides is not merely a shorthand; it creates unnecessary overhead and serves a different purpose.

    Read the full bite: Functional difference between @Binds and @Provides in Hilt

  30. Question 30 of 30

    You need to use a Hilt-provided SettingsManager inside a legacy ContentProvider. What is the proper Hilt escape hatch?

    Show the answer

    Answer: b · Create an @EntryPoint interface installed in SingletonComponent, expose SettingsManager, and retrieve it via EntryPointAccessors.fromApplication in onCreate

    The Android framework instantiates ContentProvider, so Hilt cannot perform field injection; you must define an EntryPoint in SingletonComponent and retrieve it with EntryPointAccessors.fromApplication. Option A is wrong because Hilt does not support member injection for framework-instantiated classes like ContentProvider.

    Read the full bite: How would you access a Hilt dependency in a non-injectable ContentProvider?

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon