简体   繁体   中英

Graphql Query Returning a null value (Apollo Server)

I created a mock programmatically for testing at my query but it only returns a null value what am i doing wrong. I am using the casual library for generating values for my mock

Here are my files:

index.js

   import express from 'express'
import bodyParser from 'body-parser'
import { graphqlExpress,graphiqlExpress } from 'graphql-server-express'
import { makeExecutableSchema } from 'graphql-tools'
import mock from './mock'
import schema from './schema'
const app = express()
const executableSchema = makeExecutableSchema({
    typeDefs: schema,
    mock
})

app.post(
    '/graphql',
    bodyParser.json(),
    graphqlExpress(() => ({
        schema: executableSchema
    }))
)

app.use('/graphiql',graphiqlExpress({
    endpointURL: '/graphql',
}))
app.listen(8080)
console.log("listening at 8080")

schema.js

const schema = `
interface Novel {
    artist: String
    author: String
    chapters: [Chapter]
    description: String
    genre: [String]
    id: String
    image: String
    language: String
    modified: String!
    name: String!
    status: String
    tags: [String]
    type: String
    year: String
}

interface Chapter {
chapter: String!
volume: String!
content: String!
}

type NovelCrawler implements Novel{
    artist: String
    author: String
    chapters: [Chapter]
    description: String
    genre: [String]
    id: String
    image: String
    language: String
    modified: String!
    name: String!
    novelurl: String
    status: String
    tags: [String]
    type: String
    year: String
}

type ChapterCrawler implements Chapter {
    chapter: String!
    chapterurl: String
    content: String!
    novelurl: String
    volume: String!
}
`
const Query = `
type Query {
     novels: [Novel]
}
`
export default [schema, Query]

mock.js

import casual from 'casual'
const genre = ['romance', 'comedy', 'action']
const Novel = () => ({
    artist: casual.name,
    author: casual.name,
    description: casual.sentences(3),
    genre: [casual.random_element(genre), casual.random_element(genre)],
    id: casual.url,
    image: 'sdfgrtw3wedfgb2345y675trfdvfbghdsfdssfd',
    language: casual.random_element(['chinese', 'japanese', 'korean']),
    modified: casual.date('YYYY-MM-DD'),
    name: casual.word,
    status: casual.random_element(['Completed', 'Ongoing']),
    tags: [],
    novelurl: casual.url,
    type: casual.random_element(['Web Novel', 'Light Novel']),
    year: casual.year
})

const Chapter = () => ({
    chapter: casual.integer(1, 50),
    chapterurl: casual.url,
    content: casual.sentences(10),
    novelurl: casual.url,
    volume: casual.integer(1, 5)
})

const arrNovel = []
const arrChapter = []
for (let x = 0; x < 20; ++x) {
    arrNovel.push(Novel())
    arrChapter.push(Chapter())
}

const mock = {
    // Query: { novels: () => ({}) },
    Novel: {
        __resolveType(obj, context, info) {
            return 'NovelCrawler'
        }
    },
    Chapter: {
        __resolveType(obj, context, info) {
            return 'ChapterCrawler'
        }
    },
    NovelCrawler: () => arrNovel,
    ChapterCrawler: () => arrChapter
}

export default mock

When i run the following query:

{
  novels{
    description
  }
}

it returns:

{
  "data": {
    "novels": null
  }
}

so i tried:

{
 novels{
 ... on NovelCrawler{
  artist
    }
  }
 }

this returns

 {
  "errors": [
    {
      "message": "Unknown operation named \"null\"."
    }
  ]
}

what am i doing wrong

Thanks for providing complete code and examples. Here's a few notes to get you going in the right direction:

  1. Make sure you are implementing mocks correctly. I think makeExecutableSchema used to accept a mocks option at one point, but now you have to use addMockFunctionsToSchema in conjunction with it to implement mocking. I would read Apollo's guide to mocking for detailed steps on how to do that.

  2. graphqlExpress is actually middleware, so you should implement it with app.use instead of app.post . GraphQL Server can handle both POST and GET requests.

  3. You probably don't need interfaces for what you're trying to do. An interface requires that every type that implements it also has the fields defined in the interface. They're used when two or more types share fields, which isn't the case here. I would suggest making Chapter a regular type and nesting it inside ChapterCrawler like below. Ditto for Novel.

     type ChapterCrawler { chapter: Chapter! chapterurl: String novelurl: String } type Chapter { chapter: String! content: String! volume: String! } 
  4. If you go with the above method, you will need to eventually change your query to fetch [NovelCrawler] instead. Wait! Before making things more complicated and harder to debug, I would suggest mocking just Chapter and adding a query to get [Chapters] first . Once you have that working, you'll know you have the basic functionality down and can starting mocking and querying more complex data structures.

  5. If you do need interfaces, make sure you get what function they serve and how to correctly implement them. This article may help clarify things.

  6. Keep in mind makeExecutableSchema takes typeDefs and resolvers separately once you're no longer mocking everything.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM