Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write canGetAllTodos() and get it to pass #351

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions server/src/main/java/umm3601/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

public class Main {
public static final String USER_DATA_FILE = "/users.json";
public static final String TODO_DATA_FILE = "/todos.json";

public static void main(String[] args) throws IOException {

Expand Down
20 changes: 20 additions & 0 deletions server/src/main/java/umm3601/todo/Todo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package umm3601.todo;

// Normally you'd want all fields to be private, but
// we need the fields in this class to be public since
// they will be written to by the Jackson library. We
// need to suppress the Visibility Modifier
// (https://checkstyle.sourceforge.io/config_design.html#VisibilityModifier)
// check in CheckStyle so that we don't get a failed
// build when Gradle runs CheckStyle.
@SuppressWarnings({"VisibilityModifier"})
public class Todo {
// By default Java field names shouldn't start with underscores.
// Here, though, we *have* to use the name `_id` to match the
// name of the field in the database.
@SuppressWarnings({"MemberName"}) public String _id;
public String owner;
public boolean status;
public String body;
public String category;
}
17 changes: 17 additions & 0 deletions server/src/main/java/umm3601/todo/TodoController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package umm3601.todo;

import io.javalin.http.Context;

public class TodoController {
private TodoDatabase todoDatabase;

public TodoController(TodoDatabase db) {
this.todoDatabase = db;
}

public void getTodos(Context ctx) {
Todo[] todos = todoDatabase.listTodos(ctx);
ctx.json(todos);
}

}
45 changes: 45 additions & 0 deletions server/src/main/java/umm3601/todo/TodoDatabase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package umm3601.todo;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.fasterxml.jackson.databind.ObjectMapper;

import io.javalin.http.Context;

public class TodoDatabase {
private Todo[] allTodos;

public TodoDatabase(String todoDataFile) throws IOException {
// The `.getResourceAsStream` method searches for the given resource in
// the classpath, and returns `null` if it isn't found. We want to throw
// an IOException if the data file isn't found, so we need to check for
// `null` ourselves, and throw an IOException if necessary.
InputStream resourceAsStream = getClass().getResourceAsStream(todoDataFile);
if (resourceAsStream == null) {
throw new IOException("Could not find " + todoDataFile);
}
InputStreamReader reader = new InputStreamReader(resourceAsStream);
// A Jackson JSON mapper knows how to parse JSON into sensible 'User'
// objects.
ObjectMapper objectMapper = new ObjectMapper();
// Read our user data file into an array of Todo objects.
allTodos = objectMapper.readValue(reader, Todo[].class);
}

public Integer size() {
return allTodos.length;
}

/**
* Get an array of all the todos satisfying the queries in the params.
*
* @param queryParams map of key-value pairs for the query
* @return an array of all the users matching the given criteria
*/
public Todo[] listTodos(Context ctx) {
return allTodos;
}

}
75 changes: 75 additions & 0 deletions server/src/test/java/umm3601/todo/TodoControllerSpec.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package umm3601.todo;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.verify;

import java.io.IOException;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import io.javalin.http.Context;
import umm3601.Main;

public class TodoControllerSpec {
private static TodoDatabase db;

private TodoController todoController;

@Mock
private Context ctx;

@Captor
private ArgumentCaptor<Todo[]> todoArrayCaptor;

/**
* Setup the "database" with some example todos and
* create a TodoController to exercise in the tests.
*
* @throws IOException if there are problems reading from the "database" file.
*/
@BeforeEach
public void setUp() throws IOException {
// Reset our mock context and argument captor
// (declared above with Mockito annotations @Mock and @Captor)
MockitoAnnotations.openMocks(this);
// Construct our "database"
db = new TodoDatabase(Main.TODO_DATA_FILE);
// Construct an instance of our controller which
// we'll then test.
todoController = new TodoController(db);
}

/**
* Confirm that we can get all the users.
*
* @throws IOException if there are problems reading from the "database" file.
*/
@Test
public void canGetAllTodos() throws IOException {
// Call the method on the mock context, which doesn't
// include any filters, so we should get all the todos
// back.
todoController.getTodos(ctx);

// Confirm that `json` was called with all the todos.
// The ArgumentCaptor<User[]> userArrayCaptor was initialized in the @BeforeEach
// Here, we wait to see what happens *when ctx calls the json method* in the call
// userController.getTodos(ctx) and the json method is passed a Todo[]
// (That's when the Todo[] that was passed as input to the json method is captured)
verify(ctx).json(todoArrayCaptor.capture());
// Now that the `Todo[]` that was passed as input to the json method is captured,
// we can make assertions about it. In particular, we'll assert that its length
// is the same as the size of the "database". We could also confirm that the
// particular todos are the same/correct, but that can get complicated
// since the order of the todos in the "database" isn't specified. So we'll
// just check that the counts are correct.
assertEquals(db.size(), todoArrayCaptor.getValue().length);
assertTrue(db.size() > 0);
}
}
Loading