Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java One More Time With Feeling

API tests have all started failing

All of the tests in ApiTest.java are failing for me, even though I remember them working before.

Here is the error message I'm getting:

java.net.ConnectException: Connection refused (Connection refused)

...


java.lang.RuntimeException: Whoops!  Connection error

    at com.teamtreehouse.testing.ApiClient.request(ApiClient.java:42)
    at com.teamtreehouse.courses.model.ApiTest.addingCoursesReturnsCreatedStatus(ApiTest.java:63)

This is what my Api model looks like:

package com.teamtreehouse.courses.model;

import com.google.gson.Gson;
import com.teamtreehouse.courses.dao.CourseDao;
import com.teamtreehouse.courses.dao.Sql2oCourseDao;
import com.teamtreehouse.courses.exc.ApiError;
import org.sql2o.Sql2o;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static spark.Spark.*;

public class Api {
    public static void main(String[] args) {
        String dataSource = "jdbc:h2:~/reviews.db";

        //if arguments are provided for Port and Data Source, else use defaults
        if(args.length > 0) {
            //if two arguments are not specified, api was not used correctly
            if(args.length != 2) {
                System.out.println("java api <port> <datasource>");
                System.exit(0);
            }
            //setting the port
            port(Integer.parseInt(args[0]));
            //setting the dataSource (changing the default)
            dataSource = args[1];
        }

        Sql2o sql2o = new Sql2o(
                String.format("%s;INIT=RUNSCRIPT from 'classpath:db/init.sql'", dataSource),
                "", "");
        CourseDao courseDao = new Sql2oCourseDao(sql2o);
        Gson gson = new Gson();

        //method for handling post requests:
        post("/courses", "application/json", (req, res) -> {
            //convert the body of the request (JSON) to a Course object and store it in a variable:
            Course course = gson.fromJson(req.body(), Course.class);
            courseDao.addCourse(course);
            res.status(201);
            return course;
        }, gson::toJson);

        //method for handling get requests:
        get("/courses", "application/json", (req, res) -> courseDao.findAll(), gson::toJson);

        //method for handling get requests:
        get("/courses/:id", "application/json", (req, res) -> {
            int id = Integer.parseInt(req.params("id"));
            Course course = courseDao.findById(id);
            if(course == null) {
                throw new ApiError(404, "Could not find course with id " + id);
            }
            return course;
        }, gson::toJson);

        exception(ApiError.class, (exc, req, res) -> {
            ApiError err = (ApiError) exc;
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("status", err.getStatusCode());
            jsonMap.put("errorMessage", err.getMessage());
            res.type("application/json");
            res.status(err.getStatusCode());
            res.body(gson.toJson(jsonMap));
        });

        //every response will be application/json
        //therefore we can use a filter to add the type to all responses
        after((req, res) -> {
            res.type("application/json");
        });
    }
}

And my ApiTest.java file:

package com.teamtreehouse.courses.model;

import com.google.gson.Gson;
import com.teamtreehouse.courses.dao.CourseDao;
import com.teamtreehouse.courses.dao.Sql2oCourseDao;
import com.teamtreehouse.testing.ApiClient;
import com.teamtreehouse.testing.ApiResponse;
import org.junit.*;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
import spark.Spark;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.*;

public class ApiTest {

    private static final String PORT = "4568";
    private static final String  TEST_DATASOURCE = "jdbc:h2:mem:testing";
    private Connection conn;
    private ApiClient client;
    private Sql2oCourseDao dao;
    private Gson gson;

    private Course newTestCourse() {
        return new Course("Test", "http://test.com");
    }

    @BeforeClass
    public static void startServer() {
        String[] args = {PORT, TEST_DATASOURCE};
        Api.main(args);
    }

    @AfterClass
    public static void stopServer() {
        Spark.stop();
    }

    @Before
    public void setUp() throws Exception {
        Sql2o sql2o = new Sql2o(String.format("%s;INIT=RUNSCRIPT from 'classpath:db/init.sql'", TEST_DATASOURCE), "", "");
        dao = new Sql2oCourseDao(sql2o);
        conn = sql2o.open();
        client = new ApiClient("http://localhost:" + PORT);
        gson = new Gson();

    }

    @After
    public void tearDown() throws Exception {
        conn.close();
    }

    @Test
    public void addingCoursesReturnsCreatedStatus() throws Exception {
        Map<String, String> values = new HashMap<>();
        values.put("name", "test");
        values.put("url", "http://test.com");

        ApiResponse res = client.request("POST", "/courses", gson.toJson(values));

        assertEquals(201, res.getStatusCode());

    }

    @Test
    public void coursesCanBeAccessedById() throws Exception {
        Course course = newTestCourse();
        dao.addCourse(course);

        ApiResponse res = client.request("GET", "/courses/" + course.getId());

        Course retrieved = gson.fromJson(res.getBody(), Course.class);

        assertEquals(course, retrieved);
    }

    @Test
    public void missingCoursesReturnNotFoundStatus() throws Exception {
        ApiResponse res = client.request("GET", "/courses/42");

        assertEquals(404, res.getStatusCode());
    }
}

And my ApiClient.java file:

package com.teamtreehouse.testing;

import spark.utils.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class ApiClient {
    private String server;

    public ApiClient(String server) {
        this.server = server;
    }

    public ApiResponse request(String method, String uri) {
        return request(method, uri, null);
    }

    public ApiResponse request(String method, String uri, String requestBody) {
        try {
            URL url = new URL(server + uri);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod(method);
            connection.setRequestProperty("Content-Type", "application/json");
            if (requestBody != null) {
                connection.setDoOutput(true);
                try (OutputStream os = connection.getOutputStream()) {
                    os.write(requestBody.getBytes("UTF-8"));
                }
            }
            connection.connect();
            InputStream inputStream = connection.getResponseCode() < 400 ?
                    connection.getInputStream() :
                    connection.getErrorStream();
            String body = IOUtils.toString(inputStream);
            return new ApiResponse(connection.getResponseCode(), body);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("Whoops!  Connection error");
        }
    }
}

1 Answer

Jeremiah Shore
Jeremiah Shore
31,168 Points

Can you share the output of the Run console from IntelliJ when you run those tests?