Apollo Graph - Associate

  1. What does an exclamation mark after a field's type indicate? Can have multiple choice A. The field's value can't be null. B. The field is a scalar type. C. The field's value can be null. D. The field has a default value.

The correct answer is:

a. The field's value can't be null.

An exclamation mark (!) in GraphQL indicates that a field must always return a non-null value.

b. The field is a scalar type.

  • Incorrect. The exclamation mark does not determine whether the field is a scalar type. Scalars (e.g., String, Int) and object types can both use !.

c. The field's value can be null.

  • Incorrect. The ! ensures the field cannot be null.

d. The field has a default value.

  • Incorrect. A default value is specified differently, typically in input types. The exclamation mark does not set a default value.


  1. Which of the following statements about schema-first design are FALSE? Select all that apply.

    A. Schema-first design is when the backend GraphQL API is built before the frontend client applications.

    B. Schema-first design is when teams build the structure of their GraphQL schema based on the data their clients actually need.

    C. Schema-first design relies on the backend team fully implementing the GraphQL API before the frontend team can begin their work.

    D. Schema-first design reduces overall development time, because the frontend and backend teams can work in parallel.

The FALSE statements about schema-first design are:

a. Schema-first design is when the backend GraphQL API is built before the frontend client applications.

  • False because schema-first design focuses on defining the schema first, based on client needs, not necessarily on building the backend first.

c. Schema-first design relies on the backend team fully implementing the GraphQL API before the frontend team can begin their work.

  • False because once the schema is agreed upon, frontend and backend teams can work in parallel, using mock responses or tools like GraphQL Code Generator.

b. Schema-first design is when teams build the structure of their GraphQL schema based on the data their clients actually need.

  • True because schema-first design ensures that the schema is tailored to the client's data needs.

d. Schema-first design reduces overall development time because the frontend and backend teams can work in parallel.

  • True because defining the schema upfront allows both teams to develop simultaneously without waiting on each other.

Final Answer:

The FALSE statements are a and c. 🚀


3.

type Pet {
  id: ID!
  name: String
  nicknames: [String]!
  weightInKilograms: Float!
  ageInYears: Int
  owner: Person
}

ageInYear can have A. null B. "8" C. 2 D. 4.6

The field ageInYears: Int is of type Int, which means it can hold integer values or null.

Let's analyze the options:

a. nullValid

  • ageInYears does not have an exclamation mark (!), meaning it can be null.

b. "8"Invalid

  • "8" is a string, but ageInYears is of type Int, which only allows integers.

c. 2Valid

  • 2 is a valid integer, so it's allowed.

d. 4.6Invalid

  • 4.6 is a float, but ageInYears is an Int, which only accepts whole numbers.

Final Answer:a and c are correct. 🚀


  1. Based on the schema below, which code snippet correctly defines an entry point on the Query type that returns a list of Location objects?

// Some code
type Query {
 # what goes here?
}

type Location {
 id: ID!
 name: String
 reviews: [Review!]!
}

type Review {
 id: ID!
 comment: String!
 rating: Int!
}

A. locations: [Location] B. locations(ids: [ID!]): Location C. locations: Location! D. locations: Location[]

The correct answer is:

A. locations: [Location]

Why is A Correct?

type Query {
  locations: [Location]
}
  • This defines a query named locations that returns a list of Location objects.

  • The list can be null (because there is no ! after [Location]).

  • The individual items inside the list can also be null (because there is no ! inside [Location]).

If we wanted to ensure a non-null list with non-null items, we would write:

type Query {
  locations: [Location!]!
}

Why are the other options incorrect?

B. locations(ids: [ID!]): Location

  • Incorrect because:

    • The return type is Location, meaning it returns a single Location instead of a list.

    • The query suggests filtering by ids, but it's unclear how multiple IDs would return a single Location.

C. locations: Location!

  • Incorrect because:

    • This returns a single Location, but the question asks for a list.

    • ! ensures it cannot be null, but it's still not a list.

D. locations: Location[]

  • Incorrect because:

    • GraphQL does not use TypeScript-style array syntax (Location[]).

    • Instead, GraphQL uses [Location] for lists.

Final Answer:

A. locations: [Location] is the correct way to return a list of Location objects in GraphQL. 🚀


  1. What does a resolver function do?

    A. It retrieves data from a data source for a single field on a type. B. It ensures that the schema adheres to the rules of the schema definition language (SDL). C. It defines the types and fields in a GraphQL schema file. D. It defines the entry points of a GraphQL API.

The correct answer is:

A. It retrieves data from a data source for a single field on a type.

Explanation:

A resolver function in GraphQL is responsible for fetching the data for a specific field in a type. Each field in a GraphQL schema can have its own resolver that determines how to retrieve the necessary data from a database, API, or other data sources.

Example Resolver in JavaScript (Node.js with Apollo Server):

const resolvers = {
  Query: {
    locations: () => fetchLocationsFromDB(),  // Resolver for locations query
  },
  Location: {
    reviews: (parent) => fetchReviewsByLocationId(parent.id),  // Resolver for reviews field
  }
};
  • For Query.locations, the resolver fetches a list of locations from a data source.

  • For Location.reviews, the resolver uses the id of the parent Location to retrieve related reviews.

Why the Other Options Are Incorrect?

B. It ensures that the schema adheres to the rules of the schema definition language (SDL).

  • Incorrect because SDL validation is done by the GraphQL engine, not resolvers.

C. It defines the types and fields in a GraphQL schema file.

  • Incorrect because the schema file (.graphql) defines types and fields, but resolvers handle the logic for retrieving data.

D. It defines the entry points of a GraphQL API.

  • Incorrect because entry points (queries, mutations, and subscriptions) are defined in the Query, Mutation, and Subscription types in the schema, not in resolvers.

Final Answer:

A. It retrieves data from a data source for a single field on a type. 🚀


  1. Which of the following statements about resolver function arguments is true?

    A. Resolver functions accept four optional arguments. B. Resolver functions accept three optional arguments and must always use the contextValue argument to return data C. Resolver functions accept one argument, which is destructured to the following properties: parent, args, contextValue, info D. Resolver functions are pure functions that accept one argument and have no side effects

The correct answer is:

A. Resolver functions accept four optional arguments.

Explanation:

GraphQL resolver functions can accept four optional arguments in the following order:

fieldName(parent, args, contextValue, info)

Arguments:

  1. parent – The result from the parent field (for nested resolvers).

  2. args – The arguments passed to the field in a query or mutation.

  3. contextValue – A shared object available to all resolvers (useful for authentication, databases, etc.).

  4. info – Information about the execution state of the query (e.g., field name, AST, schema details).

Example Resolver:

const resolvers = {
  Query: {
    location: (parent, args, contextValue, info) => {
      console.log(info);  // Execution details
      return fetchLocationById(args.id);  // Fetch data using args
    }
  }
};

Why the Other Options Are Incorrect?

B. Resolver functions accept three optional arguments and must always use the contextValue argument to return data.

  • Incorrect because resolvers accept four arguments.

  • Incorrect because contextValue is useful but not required to return data.

C. Resolver functions accept one argument, which is destructured to the following properties: parent, args, contextValue, info.

  • Incorrect because resolvers do not destructure a single object; instead, they receive four separate arguments.

D. Resolver functions are pure functions that accept one argument and have no side effects.

  • Incorrect because resolvers can perform side effects like making API calls, modifying a database, or logging data.

Final Answer:

A. Resolver functions accept four optional arguments. 🚀


  1. Which of a resolver's arguments is used for resolver chains, enabling a resolver function to receive the return value of the previous resolver?

    A. parent B. contextValue C. args D. info

The correct answer is:

A. parent

Explanation:

The parent argument (also called root or source in some implementations) is used in resolver chains to receive the return value of the parent field's resolver. This is important for nested resolvers, where child resolvers need data from their parent.

Example of Resolver Chaining

GraphQL Schema

type Query {
  location(id: ID!): Location
}

type Location {
  id: ID!
  name: String!
  reviews: [Review!]!
}

type Review {
  id: ID!
  comment: String!
}

Resolvers

const resolvers = {
  Query: {
    location: (parent, args, contextValue, info) => {
      return getLocationById(args.id);  // Fetch location object
    }
  },
  Location: {
    reviews: (parent, args, contextValue, info) => {
      return getReviewsByLocationId(parent.id);  // Use parent.id
    }
  }
};

How the parent Argument Works

  1. First resolver (Query.location) returns a Location object.

  2. Second resolver (Location.reviews) receives that Location as parent and uses its id to fetch related reviews.

Why the Other Options Are Incorrect?

B. contextValue

  • The contextValue argument provides shared data (e.g., authentication, database connection) across resolvers.

  • It does not pass data between resolvers in a resolver chain.

C. args

  • The args argument contains the query arguments (e.g., id: "123" in location(id: "123")).

  • It does not carry the return value from a parent resolver.

D. info

  • The info argument contains metadata about the query execution (e.g., field names, AST, schema details).

  • It is not used for resolver chaining.

Final Answer:

A. parent is the correct answer. 🚀


  1. Which of the following is NOT a benefit of using resolver chains in a GraphQL API?

A. Enabling resolver functions to handle multiple fields at once and return data from multiple data sources, resulting in faster query time B. Making resolver functions more resilient to future changes C. Keeping resolver functions lightweight and concise D. Preventing resolver functions from making extra calls for unnecessary data

The correct answer is:

A. Enabling resolver functions to handle multiple fields at once and return data from multiple data sources, resulting in faster query time

Explanation:

Resolver chains in GraphQL are designed to break down the data retrieval process into smaller, modular functions. Each resolver is responsible for fetching only the necessary data for a single field, rather than handling multiple fields at once.

While GraphQL can batch and optimize requests, resolver chains themselves do not inherently speed up query execution by handling multiple fields at once. Instead, each resolver is executed separately when needed.

Why the Other Options Are Correct?

B. Making resolver functions more resilient to future changes

  • Resolver chains help keep logic modular.

  • If the schema evolves, only the affected resolvers need updates, rather than large, monolithic resolver functions.

C. Keeping resolver functions lightweight and concise

  • Each resolver focuses on one field at a time, making them easier to read and maintain.

D. Preventing resolver functions from making extra calls for unnecessary data

  • Resolvers only fetch the fields requested by the client, avoiding over-fetching.

  • Child resolvers receive the needed parent data without unnecessary extra queries.

Final Answer:

A. Resolver chains do not inherently improve query speed by handling multiple fields at once. 🚀


  1. Given the query below, what information will be populated in the location resolver's second argument, args?

query GetLocation {
  location(id: "loc-1") {
    id
    name
    overallRating
  }
}

A. An object with an id key and "loc-1" value B. Nothing - there were no GraphQL arguments passed. C. An object containing three properties: id, name and overallRating D. An object containing all of the properties of the queried location with an id and "loc-1"

The correct answer is:

A. An object with an id key and "loc-1" value

Explanation:

The second argument of a resolver (args) contains the arguments passed to the query.

Query Provided:

query GetLocation {
  location(id: "loc-1") {
    id
    name
    overallRating
  }
}
  • The query calls location(id: "loc-1"), meaning "loc-1" is passed as the value for the id argument.

  • The resolver for location will receive args as an object with { id: "loc-1" }.

Example Resolver for location

const resolvers = {
  Query: {
    location: (parent, args, contextValue, info) => {
      console.log(args); // { id: "loc-1" }
      return getLocationById(args.id);
    }
  }
};
  • args.id will contain "loc-1", which can be used to fetch the location from a database.

Why the Other Options Are Incorrect?

B. Nothing - there were no GraphQL arguments passed.

  • Incorrect because the query explicitly passes id: "loc-1" as an argument.

C. An object containing three properties: id, name, and overallRating

  • Incorrect because args only contains arguments passed in the query, not the fields being queried.

D. An object containing all of the properties of the queried location with an id and "loc-1"

  • Incorrect because args only contains the query arguments (id: "loc-1"), not the full location data.

  • The full location data is returned by the resolver after querying the database or other data sources.

Final Answer:

A. An object with an id key and "loc-1" value 🚀


  1. Given the following schema, which field's resolver function will use the parent argument to resolve its data?

type Query {
    "The details of a specific book"
    book(id: ID!): Book
}

type Book {
    id: ID!
    name: String!
    description: String!
    numberOfPages: Int
    author: Author
}

type Author {
    id: ID!
    name: String
    numberOfBooks: Int
}

A. Book.Author B. Book.Id C. Query.Book D. Author.name

The correct answer is:

A. Book.author

Explanation:

The parent argument in a resolver is used to access the parent type’s returned data. This is relevant in nested resolvers, where a field's resolver depends on data from its parent type.

Schema Breakdown

type Query {
  book(id: ID!): Book
}

type Book {
  id: ID!
  name: String!
  description: String!
  numberOfPages: Int
  author: Author
}

type Author {
  id: ID!
  name: String
  numberOfBooks: Int
}
  • The Query.book resolver fetches a book by id.

  • The Book type includes an author field, which references another type (Author).

  • To resolve Book.author, the resolver needs to access the Book object returned by the Query.book resolver.

  • This means the parent argument will be the Book object.

Example Resolvers

const resolvers = {
  Query: {
    book: (parent, args, contextValue, info) => {
      return getBookById(args.id); // Returns a Book object
    }
  },
  Book: {
    author: (parent, args, contextValue, info) => {
      return getAuthorById(parent.authorId); // Uses parent (Book) data
    }
  }
};
  • The Query.book resolver fetches the Book object.

  • The Book.author resolver receives that Book as parent, then uses parent.authorId to fetch the author.

Why the Other Options Are Incorrect?

B. Book.id

  • Incorrect because Book.id is a scalar field, and GraphQL automatically resolves scalar fields without needing a resolver.

C. Query.book

  • Incorrect because Query.book is a root query, and root resolvers don’t have a parent object.

  • Its first argument (parent) is usually null or undefined.

D. Author.name

  • Incorrect because Author.name is a scalar field and does not need a resolver using parent.

  • If resolvers were defined for Author.name, it would use parent (the Author object), but scalar fields don’t typically need custom resolvers.

Final Answer:

A. Book.author uses the parent argument to resolve its data. 🚀


  1. Given the following schema and example query, which resolver function will NOT be called?

type Library {
    branch: String!
    books: [Book!]
    name: String!
}

type Book {
    title: String!
    author: Author!
}

type Author {
    name: String!
}

type Query {
    libraries: [Library]
}

A. Library.Name() B. Book.Author() C. Query.libraries() D. Author.name()

The correct answer is:

A. Library.name()

Explanation:

GraphQL only calls resolver functions for fields that are explicitly queried. If a field is a scalar type (like String!, Int, or Boolean) and no custom resolver is provided, GraphQL automatically resolves it by default.

Schema Provided:

type Library {
  branch: String!
  books: [Book!]
  name: String!
}

type Book {
  title: String!
  author: Author!
}

type Author {
  name: String!
}

type Query {
  libraries: [Library]
}

Example Query:

query {
  libraries {
    branch
    books {
      title
      author {
        name
      }
    }
  }
}

Which Resolvers Will Be Called?

  • Query.libraries()Called to fetch the list of libraries.

  • Book.author()Called to resolve the author field of each book.

  • Author.name()Not explicitly defined, but GraphQL automatically resolves scalar fields like name without needing a resolver.

Which Resolver Will NOT Be Called?

Library.name()NOT queried, so its resolver (if it exists) is never executed.

The query only requests branch and books from Library, so the name field is ignored. Since GraphQL executes queries field-by-field, any fields not included in the query do not trigger resolvers.

Why the Other Options Are Incorrect?

B. Book.author()

  • Called because the query requests the author of each book.

C. Query.libraries()

  • Called because the query requests the list of libraries.

D. Author.name()

  • Called, but GraphQL automatically resolves it since it’s a scalar field.

Final Answer:

A. Library.name() is NOT called because it was never requested in the query. 🚀


  1. Given the following schema, which fields accept a GraphQL argument?

type Library {
    branch: String!
    books: [Book!]
}

type Book {
    title: String!
    author: Author!
}

type Author {
    name: String!
}

type Query {
    libraries: [Library]
    book(id: ID!): Book
}

A. Only Query.book B. None of them C. All of them D. Only Library.books

The correct answer is:

A. Only Query.book

Explanation:

GraphQL arguments are explicitly defined in a schema within parentheses () after a field name.

Schema Provided:

type Library {
  branch: String!
  books: [Book!]
}

type Book {
  title: String!
  author: Author!
}

type Author {
  name: String!
}

type Query {
  libraries: [Library]
  book(id: ID!): Book
}
  • Query.book(id: ID!) has an argument id, meaning it accepts a GraphQL argument.

  • Query.libraries, Library.books, Book.title, Author.name, and other fields do not have arguments explicitly defined.

Why the Other Options Are Incorrect?

B. None of them

  • Incorrect because Query.book(id: ID!) does accept an argument.

C. All of them

  • Incorrect because only Query.book has an argument.

D. Only Library.books

  • Incorrect because Library.books does not have an argument in the schema definition.

Final Answer:

A. Only Query.book accepts a GraphQL argument. 🚀


The correct resolver function for Query.review that accesses reviewsAPI should have the following structure:

Query: {
  review: (_, args, { dataSources }) => {
    return dataSources.reviewsAPI.getReview(args.id);
  }
}

Explanation:

  1. _ is the parent argument, which is unused in this case.

  2. args contains the query parameters (e.g., { id: "review-1" }).

  3. { dataSources } is destructured from the third argument (context), allowing access to reviewsAPI.

From the images, the correct choice is the first option in the second image:

javascriptSao chépChỉnh sửaQuery: {
  review: (_, args, { dataSources }, info) => {
    // …
  }
}

This follows Apollo Server's best practices for resolvers.

You should choose the first option in the second image:

Query: {
  review: (_, args, { dataSources }, info) => {
    // …
  }
}

Explanation:

  • _ is the parent argument (not used here).

  • args contains the query arguments (e.g., { id: "review-1" }).

  • { dataSources } gives access to reviewsAPI, which is defined in the Apollo Server context.

  • info contains metadata about the execution (optional but correct in the function signature).

This option correctly follows the Apollo Server resolver function pattern.


14.

The correct answer is "args".

Explanation:

In GraphQL resolvers, the four positional arguments are:

  1. parent – The result of the parent resolver (useful for nested resolvers).

  2. args – Contains the arguments passed to the query (e.g., { id: "loc-1" }).

  3. contextValue – Shared data across all resolvers (e.g., authentication, data sources).

  4. info – Metadata about the execution state of the query.

Since the id: "loc-1" is passed as an argument in the query:

query GetLocationInformation {
  location(id: "loc-1") { ... }
}

You can access "loc-1" inside the resolver function using args.id:

location: (parent, args, contextValue, info) => {
  console.log(args.id); // "loc-1"
}

Thus, "args" is the correct choice.


15.

The correct answer is: ✅ "As strings using HTTP POST or GET requests"

Explanation:

Most GraphQL clients communicate with a GraphQL server by sending queries and mutations as JSON-encoded strings over HTTP.

  • POST requests are the most common method, where the GraphQL query is included in the request body.

  • GET requests can also be used, but the entire query is passed as a URL parameter (useful for caching).

Incorrect Answers:

"As files using SFTP" → GraphQL does not use SFTP for sending queries. ❌ "In a binary format using a GraphQL-specific networking protocol" → GraphQL primarily uses text-based JSON over HTTP, not a binary protocol.


The correct answer is: ✅ "It checks the query's Abstract Syntax Tree against the shape of its schema."

Explanation:

Apollo Server validates queries by parsing them into an Abstract Syntax Tree (AST) and then comparing the structure against the defined GraphQL schema. This ensures that:

  • The requested fields exist in the schema.

  • The query is properly formatted.

  • The types match the schema definitions.

Incorrect Answers:

"It attempts to resolve the query and flags it as invalid if any resolvers fail." → Resolvers execute after validation. Validation happens before execution. ❌ "It verifies that a custom resolver has been defined for every field included in the query." → Fields can have default resolvers; Apollo doesn't require custom resolvers for all fields. ❌ "It checks the HTTP headers of the request." → While Apollo Server may check headers for authentication, that is not part of query validation.


17.

The correct answer is: ✅ "A requested field returns an object type, but no additional subfields were included."

Explanation:

In the provided query:

query GetAvailableBooks {
  availableBooks {
    id
    title
    pages
    author
  }
}
  • The author field in Book is of type Author, which is an object type.

  • GraphQL requires you to explicitly request subfields for object types.

  • The query does not specify subfields for author, so the server will throw an error.

How to Fix:

You should request subfields like this:

query GetAvailableBooks {
  availableBooks {
    id
    title
    pages
    author {
      id
      name
      bio
    }
  }
}

Now, the author field includes id, name, and bio, making it a valid query.


18.

The correct answers are: ✅ "A mutation is a write operation.""A mutation modifies backend data."

Explanation:

  • A mutation is a write operation → ✅ Correct.

    • GraphQL mutations are used to create, update, or delete data (write operations).

  • A mutation is a read-only operation → ❌ Incorrect.

    • Read-only operations are handled by queries, not mutations.

  • A mutation modifies backend data → ✅ Correct.

    • Mutations typically modify data in a database or another backend system.

  • A mutation modifies the server's schema → ❌ Incorrect.

    • The schema is defined statically in GraphQL and does not change through mutations.


19.

The correct answer is: ✅ "Any number of data sources can be used to create an API that serves the needs of a client app."

Explanation:

  • "Any number of data sources can be used to create an API that serves the needs of a client app." → ✅ Correct.

    • Apollo Server allows you to integrate multiple data sources (e.g., databases, REST APIs, third-party services) to fetch and aggregate data efficiently.

  • "Each type in a schema should have a corresponding data source that is used in its fields' resolver functions." → ❌ Incorrect.

    • While data sources are commonly used in resolvers, not every type in a schema requires a direct data source. Some types may be derived from other types or computed fields.

  • "Data sources need to be implemented in a standard way to ensure that queries can be executed consistently." → ❌ Incorrect.

    • While using Apollo’s DataSource class provides consistency, there is no strict requirement to implement data sources in a specific standard way. Custom implementations are possible.

  • "Apollo Server is not concerned with data sources." → ❌ Incorrect.

    • Apollo Server provides built-in support for data sources, especially when working with REST and databases. It helps manage data fetching efficiently with caching and batching.


20.

The correct answer is: ✅ "The dataSources property should be passed into the ApolloServer constructor."

Explanation:

The issue in the given code is that the dataSources property is being passed to startStandaloneServer instead of being included inside the ApolloServer constructor. The correct way to define data sources is to pass them inside ApolloServer like this:

const server = new ApolloServer({ 
  typeDefs, 
  resolvers,
  dataSources: () => ({ booksAPI: new BooksAPI() }) // Move this here
});

Why the other options are incorrect:

  • "The dataSources property should be returned inside the object returned by the context function." → ❌ Incorrect

    • dataSources should not be part of context. Apollo Server automatically provides it to resolvers.

  • "The context property should be passed into the ApolloServer constructor." → ❌ Incorrect

    • While context can be passed to ApolloServer, it's not required in this case. The issue is specifically with dataSources.

  • "The dataSources property should always include more than one instance of a data source." → ❌ Incorrect

    • There is no requirement to always have multiple data sources. A single data source is valid.


21.

The correct answer is: ✅ "The getBookGenres method needs to be accessed from the booksAPI property on dataSources, rather than being called directly."

Explanation:

In the resolver function, dataSources is an object containing different data sources, including booksAPI. The function is incorrectly calling dataSources.getBookGenres() directly. Instead, it should access the getBookGenres method from the booksAPI property:

Corrected Code:

bookGenres: (_, __, { dataSources }) => {
  return dataSources.booksAPI.getBookGenres(); // Corrected access
};

Why the other options are incorrect?

  • "The getBookGenres method shouldn't be called within the resolver function, but should be returned instead." → ❌ Incorrect

    • The function should call getBookGenres() inside the resolver. The issue is how it's accessed, not that it's being called.

  • "The dataSources property shouldn't be destructured from the third argument to the resolver function." → ❌ Incorrect

    • dataSources is correctly destructured from the third argument, which represents the context in Apollo Server.

  • "The dataSources property should be destructured from the first argument to the resolver function, rather than the third." → ❌ Incorrect

    • The first argument in a resolver is usually the parent object (which is unused here). dataSources correctly belongs to the context (third argument).


22.

The correct answer is: ✅ "To receive incoming GraphQL queries from a client, validate them against a schema, and populate a response."

Explanation:

Apollo Server is a GraphQL server that:

  1. Receives GraphQL queries from clients.

  2. Validates them against a defined schema.

  3. Resolves the queries by fetching and returning data.

Why the other options are incorrect?

  • "To manage the cookies and other application state data in the browser" → ❌ Incorrect

    • This is typically handled by frontend frameworks like Apollo Client, not Apollo Server.

  • "To handle the end-to-end lifecycle of a query, starting from its implementation in a frontend application" → ❌ Incorrect

    • Apollo Server only manages the backend GraphQL API; the frontend part is handled by Apollo Client or other libraries.

  • "To host and manage database records as a content management system (CMS)" → ❌ Incorrect

    • Apollo Server does not act as a CMS. It can fetch data from databases but does not manage them directly like a CMS would.


23.

The correct answer is: ✅ "Passing an array of clients that will query the server for data"

Explanation:

To initialize Apollo Server properly, the required steps include:

  1. Passing typeDefs and resolvers – These define the GraphQL schema and how queries are resolved.

  2. Defining a context function – This allows instantiation of BookingsAPI in dataSources, providing access to external data sources.

  3. Calling the startApolloServer function – This starts the server asynchronously.

Why is "Passing an array of clients" NOT required?

  • Apollo Server does not require knowledge of the clients that will query it.

  • Clients (e.g., Apollo Client, Relay, Fetch) interact with the GraphQL API but do not need to be explicitly passed into the server setup.


24.

The correct answer is: ✅ "Adding a listen property to the standalone server's options object, which specifies an object with a port property"

Explanation:

To allow the Apollo Server to listen for incoming requests on a specific port, you must specify the port in the startStandaloneServer function. The missing piece in the implementation is adding the listen property:

Correct Implementation:

await startStandaloneServer(server, {
  listen: { port: 4000 },  // Specify the port here
  context: async () => {
    return {
      dataSources: {
        reviewsAPI: new ReviewsAPI(),
      },
    };
  },
});

Why are the other options incorrect?

"Passing in a port property to the ApolloServer constructor"

  • The ApolloServer constructor does not accept a port property. The correct place to define it is in startStandaloneServer.

"Specifying in the ApolloServer constructor that the server should be open to requests"

  • There is no open property in ApolloServer. The server automatically listens when configured properly.

"There's nothing missing from this implementation; the functions defined in resolvers will handle requests."

  • The resolvers define how queries/mutations are processed, but without a specified port, the server won't listen for incoming requests.

Thus, adding listen: { port: 4000 } ensures the server monitors a specific port. 🚀


25.

The correct answers are: ✅ "The ApolloProvider component is passed a prop named client.""The ApolloProvider component makes an Apollo Client instance available throughout a React component tree."

Explanation:

  1. "The ApolloProvider component is passed a prop named client."

    • This is correct. The ApolloProvider component requires a client prop, which is an instance of ApolloClient.

    • Example:

      import { ApolloProvider, ApolloClient, InMemoryCache } from '@apollo/client';
      
      const client = new ApolloClient({
        uri: 'https://example.com/graphql',
        cache: new InMemoryCache()
      });
      
      function App() {
        return (
          <ApolloProvider client={client}>
            <MyComponent />
          </ApolloProvider>
        );
      }
  2. "The ApolloProvider component accepts a configuration object, on which a uri for a GraphQL server can be set."

    • Incorrect because ApolloProvider itself does not accept a configuration object with a uri. Instead, the ApolloClient instance (which is passed as the client prop) is where the uri is configured.

  3. "The ApolloProvider component makes an Apollo Client instance available throughout a React component tree."

    • Correct. ApolloProvider wraps the React component tree, making the Apollo Client instance accessible to any child component that uses hooks like useQuery or useMutation.

  4. "The ApolloProvider component is a wrapper that needs to be instantiated in every React component that sends GraphQL queries to a backend."

    • Incorrect. You only need to wrap the top-level component once, and all child components will have access to Apollo Client without needing another ApolloProvider.

Final Answers: ✅ 1st and 3rd statements. 🚀


26.

The correct answers are: ✅ dataloadingerror

Explanation:

When using Apollo Client’s useQuery hook in React, it returns an object containing several properties, including:

  1. data

    • This property contains the result of the GraphQL query.

    • If the query is successful, data will hold the returned values.

    • Example usage:

      const { data } = useQuery(GET_USERS);
      console.log(data); // Logs fetched data from the query
  2. loading

    • This is a boolean that indicates whether the query is still in progress.

    • If loading is true, the request has not completed yet.

    • Example usage:

      const { loading } = useQuery(GET_USERS);
      if (loading) return <p>Loading...</p>;
  3. error

    • If an error occurs while fetching data, this property contains the error object.

    • If there is no error, error will be undefined or null.

    • Example usage:

      const { error } = useQuery(GET_USERS);
      if (error) return <p>Error: {error.message}</p>;

Incorrect options:

  1. result

    • There is no result property in the object returned by useQuery.

    • The data property holds the query result.

Final Answers:data, loading, error 🚀


27.

The correct answers are: ✅ Updating an existing value in a backend databaseInserting a new value into a backend database

Explanation:

In Apollo Client, the useMutation hook is used to perform GraphQL mutations, which are operations that modify data on the server, such as:

  • Creating (inserting) new records

  • Updating existing records

  • Deleting records

Valid use cases for useMutation:

  1. Updating an existing value in a backend database

    • Example: Changing a user's email or updating a post's content.

    • Example mutation:

      const UPDATE_USER = gql`
        mutation UpdateUser($id: ID!, $email: String!) {
          updateUser(id: $id, email: $email) {
            id
            email
          }
        }
      `;
      const [updateUser] = useMutation(UPDATE_USER);
  2. Inserting a new value into a backend database

    • Example: Creating a new user or adding a new post.

    • Example mutation:

      const ADD_USER = gql`
        mutation AddUser($name: String!, $email: String!) {
          addUser(name: $name, email: $email) {
            id
            name
          }
        }
      `;
      const [addUser] = useMutation(ADD_USER);

Incorrect options:

  1. Renaming a field in a backend schema

    • This is a schema design change, which is done at the GraphQL schema level, not through a mutation.

  2. Defining a new entry point on a schema's Mutation type

    • This is a backend configuration step that involves modifying the GraphQL schema, not executing a mutation in the client.

Final Answers: ✅ Updating an existing value, ✅ Inserting a new value 🚀


28.

The correct answer is: ✅ ASSIGN_SPACESHIP_MUTATION

Explanation:

The useMutation hook in Apollo Client is used to perform GraphQL mutations. The first argument passed into useMutation must be the GraphQL mutation document, which in this case is ASSIGN_SPACESHIP_MUTATION.

How useMutation works:

const [assignSpaceship, { loading, error, data }] = useMutation(ASSIGN_SPACESHIP_MUTATION);
  • The first argument is the mutation document (gql query).

  • The returned function (assignSpaceship) is used to execute the mutation.

  • loading, error, and data provide the mutation state.

Why the other options are incorrect:

{ spaceshipId, missionId } → This is the variables object that should be passed when calling the mutation, not when defining it.

AssignSpaceshipToMission → This is just the mutation name inside the gql query; it’s not the correct argument for useMutation.

{ variables: { spaceshipId, missionId } } → This is part of the second argument when calling the mutation, not the first argument to useMutation.

Correct Usage:

const [assignSpaceship] = useMutation(ASSIGN_SPACESHIP_MUTATION);

assignSpaceship({
  variables: { spaceshipId, missionId }
});

Thus, the first argument should be ASSIGN_SPACESHIP_MUTATION ✅.


29.

The correct answer is: ✅ "To build and execute queries against a registered schema"

Explanation:

GraphOS Studio's Explorer tool (part of Apollo Studio) is designed to help developers build, explore, and execute GraphQL queries against a registered schema. It provides a graphical interface where users can:

  • Write and execute GraphQL queries and mutations

  • Explore available types, fields, and operations

  • Test queries without needing to write them manually

Why the other options are incorrect?

"To automate server package installation and database configuration"

  • GraphOS Studio does not handle server automation or database setup.

"To audit the backend server for potential bugs and syntax errors"

  • While Explorer can validate queries, it does not perform full backend audits for bugs.

"To simulate how users will interact with an app’s frontend"

  • Explorer is used for GraphQL query testing, not UI/UX simulation.

Thus, the best choice is "To build and execute queries against a registered schema" ✅.

Last updated