Controller Testing9:39 with Chris Ramacciotti
In this video we begin our work in testing the weather app, starting with our controllers. The Spring test framework provides some nice features for testing requests to specific URIs without firing up an entire Spring application.
Mock MVC Result Matchers
What you "expect" after performing a request on a
MockMvc object is called a
ResultMatcher. Typically your options will come from the
MockMvcResultMatchers class. Some things you can examine are the following:
content(): check the response body for actual content in the HTTP response
flash(): check for certain flash attributes
model(): check for model attributes
jsonPath(...): check for content in an HTTP response body that is in the JSON format (e.g. for a REST API)
For a full list of matchers, see the Spring docs for org.springframework.test.web.servlet.result.MockMvcResultMatchers.
Sync Your Code to the Start of this Video
git checkout -f v3
Using Git with this Workshop
See the README on Github for information on how to use Git with this repo to follow along with this workshop.
You've had a chance to see the code base so it's time we dive into some testing. 0:00 Now whereas the code you've explored so 0:03 far resides in the main source directory, the code that we'll write during 0:05 this workshop will live in the test source directory, so let's open that now. 0:09 In here there's exactly one package com. 0:13 teamtreehouse.web.controller and in that package one class weather controller test. 0:16 Let's open that now. 0:22 What I'll do in this workshop is show you how to test spring 0:23 components starting with the controller like this one then 0:26 working our way towards the database by moving to services and finally to DAO's. 0:29 Let's begin by testing the weather controller in this class weather 0:34 controller test. 0:37 Now for each method in a controller we'd want to write at least one test and 0:38 even more if we have boundary cases to consider. 0:43 Remember those are the special cases that won't happen often or maybe hardly ever. 0:45 But we want to make sure application doesn't blow up 0:50 in the event that the unlikely occurs at any rate. 0:52 Let's start by testing this controller for 0:56 what happens when the home page is requested. 0:58 So if we open the weather controller. 1:01 And scroll down to where the home page is requested which is at the bottom here. 1:06 We see that the only thing that this method does is render 1:12 the weather/detail template. 1:15 So let's make sure it does just that. 1:18 First though, we need to set up our mock environment. 1:20 So back in WeatherControllerTest, 1:24 we are going to have to set up our mock environment. 1:25 Now typically when we run a spring application, the overall shell or 1:28 container that we are starting is called an application context. 1:31 This is a spring container that loads and manages bean definitions, 1:37 like the methods that you've annotated with bean in your config files. 1:40 Or all those classes you've annotated with controller, service, repository, and 1:44 component. 1:49 Now, all of this is a bit overkill for our unit test. 1:50 That is, loading all these definitions. 1:53 We don't need all those being definitions and the extra functionality provided by 1:55 the application context just for testing purposes. 1:58 If we were to load the context, that would be an integration test. 2:02 Integration tests are important but they are not the subject of this workshop. 2:06 Be sure to check the teacher's notes for more on the spring application context. 2:10 Instead of loading an entire application context here, what we'll do is create 2:15 a fake or mock MVC object through which we can run all requests to our application 2:19 and we won't need to fire up the entire context which would take more time anyway. 2:24 So to begin, let's set up a mock MVC object. 2:29 I'll declare it as a field so I can reuse it within the individual test methods. 2:32 Private MockMVC, there it is right there, and I'll call it mockMVC. 2:36 We'll also need a controller to set up that mocked MVC framework, so 2:44 let's declare one of those too. 2:47 Private WeatherController that's our controller under test here and 2:48 I'll just name that controller. 2:52 As you've seen with unit testing in the past we can include a method in J Unit 2:56 tests that is sure to execute once before each of the test methods is executed. 3:01 Let's use that method to set up our controller and mock NBC objects. 3:06 So public void, I'll name it setup, that's the standard name for 3:10 one of these methods. 3:14 And let's set up the controller. 3:15 So I'll create a new weather controller excellent. 3:18 And let's also set up the mock MVC object. 3:22 Now this object is set up with the builder pattern so 3:25 mock MVC builders right here and will choose the standalone set up and 3:29 pass to it the controller that we just created and 3:34 to build the object and store it into the mock MVC field. 3:39 I will call this builders build method. 3:42 Okay, time to write our first test. 3:45 Again, we wanna test that a request to our home page renders the weather detail view. 3:48 Let's name our method accordingly. 3:52 I'll annotate this with J units test annotation and I'll call it public void. 3:54 And the home should render the detail view. 4:01 And I'll say it throws an exception. 4:05 As for the test code, we'll start by using the mockMvc object to perform a get 4:11 request, so mockMvc.perform And 4:15 what we can do here is use the mock N.B.C. request builder's class. 4:21 So if you arrow down there you see it right there and 4:25 we'll use the get method and in parentheses here the parameter 4:29 value we want to pass is the U.R.I. that we'd like to perform a get request to. 4:34 Now for convenience, let's do a static import of this 4:39 mockMvcRequestBuilders class, all of its methods. 4:43 So here we have that right here. 4:48 I'm going to move this down here and 4:52 do an import static of all its methods. 4:56 And I'll be sure to change that second import statement to static. 5:02 Cool. 5:08 Now I can remove this right here, and 5:10 that get method is called in a much more succinct 5:13 after this call to the mock NBC's perform method, we can write 5:19 expectations which are like assertions by chaining method calls right here. 5:22 For example, let's expect that the view name is weather slash detail. 5:27 So we'll write andExpect. 5:32 And in here, we can use a MockMvcResult matcher and 5:35 all say that it's view name so, view it's 5:41 name is equal to weather/detail. 5:47 Let me put this on a couple lines so you can see it in my code window here. 5:52 Give us a little more room there we go let's do that right there. 5:58 Okay, let's do the same thing for this mock NBC result matchers methods 6:05 as we did for the mock NBC request builders right here. 6:10 So I'm going to move that down here under my static imports. 6:13 So import static will say all its methods and 6:19 I can get rid of this using its static methods quite a bit. 6:24 So this allows us to write much shorter code and 6:29 just like that we have our first test. 6:33 Now let's run it. 6:35 I'll make sure to save my file here. 6:38 And with the weather controller test editor in focus all use 6:40 control shift R to run this test. 6:45 What you should get is a panel that pops up at the bottom showing the success or 6:49 failure of this test. 6:53 And great looks like our test Passes, we got green. 6:56 Let me show you one more test before we start looking at mocking objects. 7:02 Let's test the weather controller's search method. 7:06 So, back in the weather controller class, 7:09 let's see what the search method does here. 7:11 The method currently accept a URL query string parameter and 7:15 redirects to a URI with a path parameter. 7:19 Let's make sure in our tests that this actually happens. 7:24 So let's go back to the test. 7:27 I'll start by stepping out a method according to what I'd like the test to 7:30 examine. 7:33 So let's write a second test down here. 7:34 I'll name this one public void search_ShouldRedirectWithPathParam(). 7:38 Cool, and in that method, let's perform 7:52 a get request to the /search URI, so mockMvc.perform. 7:56 And again this is a GET request to the slash search you are I 8:02 know what we need to do is we need to add to that query string parameter to the GET 8:10 request so after the call to get I will call the param method. 8:14 The parameter name is q and the value I'd like to pass is 60657 and 8:19 what we expect is that this request 8:25 redirects to /search/60657. 8:29 So let's do that now let me put this on the next line here .andExpect. 8:35 I will say redirectedUrl. 8:42 That's another method that comes from this MockMvcResultMatchers class. 8:46 So I want to expect that the redirected URL is /search/60657. 8:51 I'll put my semi colon at the end here. 8:59 There are lots of things that you can include as an expectation. 9:02 Check the teacher's notes for more. 9:05 Okay, let's run both these tests and see if we're still in the green, 9:09 control shift r and let's watch both of our tests run and hopefully succeed. 9:12 Excellent, it says all two tests have passed and I see the names of those tests. 9:19 Right here. 9:24 Now, though we're green, we've only just begun. 9:27 Next I'll introduce you to the powerful world of mocking. 9:29 No I don't mean giving other people hard time. 9:33 I mean faking objects. 9:36 You'll see what I mean. 9:38
You need to sign up for Treehouse in order to download course files.Sign up