Lab02 fries
In this lab, you'll add support for ordering Fries, starting with the MealBuilder
class, adding that property to the request object, and then have the API Controller method process it and return the price.
Add Fries Support to MealBuilder¶
Starting with the test, go to MealBuilderTest
and add the following:
@Test
public void orderWithBurgerCheeseAndLargeFriesIs11Dollars() throws Exception {
MealBuilder mealBuilder = new MealBuilder();
mealBuilder.addBurgerString("cheese");
mealBuilder.withFries("large");
// use the build() method to create a meal order
// assert that the price is burger (5) + cheese (1) + large-fries (5)
assertThat(...
}
Run it and it should fail.
Make Test Pass¶
In order to make this test pass, you will have to:
-
Add the
withFries
method toMealBuilder
and store the size in aString
instance variable calledfriesSize
-
Inside the
MealBuilder.build()
method, add code to add the fries to the meal order:public MealOrder build() { // existing build code here **Add the Fries to the mealOrder HERE** return mealOrder; }
Question
What happens for tests that didn't specify any Fries?
Do NOT change the tests to "fix" this problem: fix the code.
-
Make sure the
MealBuilderTest
tests pass.
Run All Tests
Make sure all of your tests pass before going to the next step.
Update the API Controller¶
Now let's make the API support ordering fries. First let's make sure we have a failing test.
Add Fries to Request¶
- Add the
friesSize
property to theMealOrderRequest
class: instance variable, and getter/setter.
Add Test for Fries¶
-
Go to the
MealOrderApiControllerTest
test and write a new test that is similar to the one that's already there: instead of setting the drink, set thefriesSize
property, e.g.:public class MealOrderApiControllerTest { // ... other test... @Test public void ...your test name here...() throws Exception { // GIVEN a request (similar to above)... mealOrderRequest.setFriesSize("large"); // $5 // WHEN calling controller.mealOrder... // THEN assertThat the response has the right price... } }
Outcome?
What is the total price for an order with a large fries? Make sure to assert that.
-
Make sure the test fails before continuing.
Add Support in Controller¶
-
Add code in the
mealOrder
method inMealOrderApiController
so that if a Fries Size is specified, it's added to the meal order. -
Does the
MealOrderApiControllerTest
now pass? It should!
Run All Tests
Make sure all of your tests pass before going to the next step.
Try it Out¶
-
Start the app by running the
MealKioskApplication
class -
Use this URL in either curl or Postman:
localhost:8080/api/mealorder
curl on Windows¶
curl -v -d "{\"burger\": \"cheese\", \"drinkSize\": \"large\", \"friesSize\": \"regular\"}" -H "Content-Type: application/json" localhost:8080/api/mealorder
curl on Mac¶
curl -v -d '{"burger": "cheese", "drinkSize": "large", "friesSize": "regular"}' -H 'Content-Type: application/json' localhost:8080/api/mealorder
Postman¶
Do a POST to
localhost:8080/api/mealorder
with the following JSON{"burger": "cheese", "drinkSize": "large", "friesSize": "regular"}
-
You should see the following JSON because Burger w/Cheese (6), Large Drink (2), and Regular Fries ($3) = $11.
{"price": 11}
Instructor Check-in¶
Before going any further, have the instructor look over your work.
Bonus (Optional)¶
The builder could use some improvements to become more "fluent". It would be nice if instead of
MealBuilder mealBuilder = new MealBuilder();
mealBuilder.addBurgerString("none");
mealBuilder.withDrink("regular");
mealBuilder.withFries("large");
MealOrder mealOrder = mealBuilder.build();
we could write
MealOrder mealOrder = MealBuilder.builder()
.burger("none")
.drink("regular")
.fries("large")
.build()
This is called a "fluent" or "chained" builder.
Rename Methods¶
First we'll rename the methods on the builder using IntelliJ IDEA's Refactoring > Rename tool.
- Find the
addBurgerString
method - With the cursor on that method, use the Refactor > Rename menu item (or Shift + F6) to rename it to
burger
- Find the
withDrink
method and rename it todrink
- Find the
withFries
method and rename it tofries
Make sure all tests still pass before continuing.
Return Builder¶
Now we'll change all the builder methods to return an instance of the builder (itself).
-
In the
burger
method, change the signature to return aMealBuilder
and then returnthis
, so you want the method to look like:public MealBuilder burger(String burgerOrderString) { burgerOrder = burgerOrderString; return this; }
-
Do the same for
drink
- And the same for
fries
Make sure all tests still pass before continuing.
Create Builder Method¶
Create a new method, builder()
that is static
and returns a new instance of the MealBuilder
.
Change Tests to Use Fluent Builder¶
Inside of the MealBuilderTest
test class, pick one of the tests that builds from multiple items and convert it so that it uses this new fluent syntax, e.g., write a Builder test that uses:
MealOrder mealOrder = MealBuilder.builder()
.burger("none")
.drink("regular")
.fries("large")
.build()