GraphQL Caused by: graphql.AssertException: you must provide a data fetcher. How to stub data fetcher here?

713 Views Asked by At

I am trying to write JUnit test for GraphQl with Spring Boot. My test fails at the below method. I am getting AsserException at treeWiring.abcFetcher. (Caused by: graphql.AssertException: you must provide a data fetcher). PLease help me how to mock the data fetcher. Its value is showing as null.

private RuntimeWiring buildWiring() {
            return RuntimeWiring.newRuntimeWiring()
                    .type(newTypeWiring("Query")
                            .dataFetcher("xList", abcWiring.abcDataFetcher));

Below is my source class

@Component
public class GraphQLProvider {
    private GraphQL graphQL;
    private TreeWiring abcWiring;




    @Autowired
    public GraphQLProvider(TreeWiring abcWiring) {
        this.abcWiring = abcWiring;
    }

    @PostConstruct
    public void init() throws IOException {
        URL url = Resources.getResource("graphql/x.graphqls");
        String sdl = Resources.toString(url, Charsets.UTF_8);
        GraphQLSchema graphQLSchema = buildSchema(sdl);

        Instrumentation instrumentation = new TracingInstrumentation();

        DataLoaderRegistry registry = new DataLoaderRegistry();
        DataLoaderDispatcherInstrumentation dispatcherInstrumentation
                = new DataLoaderDispatcherInstrumentation(registry);

        this.graphQL = GraphQL.newGraphQL(graphQLSchema).instrumentation(instrumentation).instrumentation(dispatcherInstrumentation).build();
    }

    private GraphQLSchema buildSchema(String sdl) {
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
        RuntimeWiring runtimeWiring = buildWiring();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
    }

    private RuntimeWiring buildWiring() {
        return RuntimeWiring.newRuntimeWiring()
                .type(newTypeWiring("Query")
                        .dataFetcher("xList", abcWiring.abcDataFetcher));

Below is my TestCLass:

@ContextConfiguration(classes = GraphQLProvider.class)
@SpringBootTest
@RunWith(SpringRunner.class)
public class GraphQLProviderTest {


    @MockBean
    TreeWiring treeWiring;


    @MockBean
    DataFetcher abcDataFetcher;

    //@InjectMocks
    //GraphQLProvider graphQLProvider = new GraphQLProvider(treeWiring);

    @Autowired
    @InjectMocks
    GraphQLProvider graphQLProvider;



    @Before
      public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testGetUserLabels() throws IOException  {
        Mockito.when(treeWiring.db2HealthDataFetcher).thenReturn(db2HealthDataFetcher);
        graphQLProvider.init();
    }


}

Below is my TreeWiring code:

@Component
public class TreeWiring {

@Autowired
    public TreeWiring(OneRepository oneRepository,
            TwoRepository twoRepository,
            ThreeRepository threeRepository,
            FourRepository fourRepository) {
        this.oneRepository = oneRepository;
        this.twoRepository = twoRepository;
        this.threeRepository =threeRepository;
        this.fourRepository = fourRepository;
    }


DataFetcher abcDataFetcher = environment -> {   

        String eID = environment.getArgument("eId");
        String dID = environment.getArgument("dId");

return oneRepository.getUserLabel(eID);
1

There are 1 best solutions below

2
On

In your JUnit test class, you are mocking the DataFetcher abcDataFetcher, but you are not setting it up to be used in the TreeWiring class. That's why you are getting a NullPointerException when trying to use it.

To fix this, you need to properly set up the abcDataFetcher mock and pass it to the TreeWiring instance used in your GraphQLProvider. Here's how you can do it:

  1. Modify the test class to set up the abcDataFetcher mock and pass it to the TreeWiring instance:
@ContextConfiguration(classes = GraphQLProvider.class)
@SpringBootTest
@RunWith(SpringRunner.class)
public class GraphQLProviderTest {

    @MockBean
    TreeWiring treeWiring;

    @MockBean
    DataFetcher abcDataFetcher;

    @Autowired
    GraphQLProvider graphQLProvider;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        // Set up the mock behavior for abcDataFetcher
        Mockito.when(treeWiring.abcDataFetcher).thenReturn(abcDataFetcher);
    }

    @Test
    public void testGetUserLabels() throws IOException {
        // You can optionally set up the behavior for abcDataFetcher here if needed.
        // Mockito.when(abcDataFetcher.get(...)).thenReturn(...);

        // Now, call the init() method on the graphQLProvider to test it.
        graphQLProvider.init();
    }
}
  1. Make sure the TreeWiring class is correctly set up with the abcDataFetcher:

    @Component
    public class TreeWiring {

        private final OneRepository oneRepository;
        private final TwoRepository twoRepository;
        private final ThreeRepository threeRepository;
        private final FourRepository fourRepository;

        @Autowired
        public TreeWiring(OneRepository oneRepository,
                          TwoRepository twoRepository,
                          ThreeRepository threeRepository,
                          FourRepository fourRepository,
                          DataFetcher abcDataFetcher) { // Inject the DataFetcher here
            this.oneRepository = oneRepository;
            this.twoRepository = twoRepository;
            this.threeRepository = threeRepository;
            this.fourRepository = fourRepository;
            this.abcDataFetcher = abcDataFetcher; // Set the DataFetcher for this instance
        }

        // Rest of your TreeWiring class implementation...

    }

By properly setting up the abcDataFetcher mock and passing it to the TreeWiring class, the null value issue should be resolved, and your test should run without any NullPointerException.