Spring Boot Rest Client - How to test HTTP calls using @RestClientTest

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] you're working on a new spring application that needs to talk to another service over HTTP you could reach for a couple different options here you could use the rest template you could use the web client or you can use spring boot 3. 2's new rest client now the question becomes how are you going to test this you can write an integration test that talks to the actual service but what happens if the service is down or maybe it's not even written yet you have a few different options here but I'm going to show you one today which is the at rest client test annotation hi my name is Dan Vega I'm a spring developer Advocate at broadcom and I make videos about Java spring or anything that interests me so if that sounds like your cup of tea do me a favor and subscribe and let me know in the comments below what you're interested in learning about So today we're going to create a new application we'll create a simple HTTP call using the new rest clein but I want to focus on the testing side of things and we'll look at the sanitation and take a a look at how it helps you write these tests quickly with that let's head over to start. spring.io and create a new app all right here I am on start. spring.io I'm going to say that this is a Java app a maven app I'm using the latest version of spring boot which is 3.2.2 you need to be on at least 3.2 to take advantage of the rest client now this will work with the rest template as well so if you're using that uh this test annotation will work so I'm going to say dev. Dan Vega the artifact will be uh let's say RC uh test now I will leave a link to a GitHub repository in the description below that contains a bunch of examples around the rest client that I'm doing I'm just creating a separate uh example here so that we can focus on this one so I'm going to choose Java 21 you can choose Java 17 and the only dependency will'll need is spring web so I'll go ahead and generate that download that and I'll open it up in my favorite ID and intellig idea ultimate but this will work in any ID or text editor that you're most productive in all right I'm going to move quickly through this first section we've done this on this channel before I want to get to the testing side of things so I'm just going to create a couple classes one is going to be a post record this is going to represent a post in our system and integer user id id string title string body that looks exactly like what we need uh again we're using a Json placeholder service a public API that we can talk to so that looks like that'll be exactly what we need so I'm also going to create another class I'm going to call this the post client and we'll go ahead and Mark this with at components so this gets picked up uh we'll do something quickly here we're going to I have a intell live template that creates a new rest client for me I've talked about this in the past if you want to find out more about all the things we're doing with the rest client the GitHub repo has a read me with all the tutorials we're doing around around this but this gives us a rest client we need to set a base URL so we'll say base oops. base URL and yes we are talking to the Json placeholder service so I need a method here that will return a list of posts and we'll call this find all and then we'll just return the rest client we'll call get method the URI on this is going to be SL posts uh we are going to retrieve this and then we'll turn this into a list of posts and we'll do that using the parameter parameterized type reference uh so no um we don't need that and this looks good so you could have list of posts here you can also just uh omit that if you want to and that looks like everything we need uh that should be good so now the question is how do we test this right so I want to write a test for this I'm going to come up here and say generate and we're going to generate a test and we'll call this the post client test and yes I want to test this find all method so how do we do this we could come in here and say okay go ahead and autowire me in that post client right now I have the post client I can make a call out to the post client and go ahead and use that but the problem with that is is that we're going to actually be using the actual rest client to call out to the public API and that may be just fine that may be exactly what you're trying to do in my case I want to write a test that doesn't assume that it's available so maybe it's down maybe it's not written yet I want to just write a test where I'm kind of mocking that out so what I'm going to do is start with the at rest client test annotation and pass in the class that I'm testing I want to drill into this annotation so we can take a look at it real quick um this is uh annotation for spring rest client test that focuses only on beans that use the rest template Builder or the rest client Builder and if you remember back in my post client that's how I got an instance of this through the rest client. Builder using this annotation will disable full auto configuration and instead only apply configuration relevant to the rest of the test I.E Jackson or gson Auto configuration any Json component beans uh but not regular component beans uh so that's that's important but again um because we have that rest client Builder uh we'll be able to to use that here so here's some good information on that particular one so now what I want to do is actually let me drill back into that one of the things that it does is it autoc configures a mock rest service server and this will give us the ability to kind of mock that out so I'm going to say uh at autowired and we're going to say Mach rest service server I'm going to call this actually let's call This Server and now we have that one other thing I'm going to go ahead and bring in and we'll do that in a second so let's change the name of this I like to say should find all posts and now what I need to do is do something like this I'm going to say yeah given when then so given is okay I want to kind of set this up right and to give uh what basically what we're doing here is we're setting up some data so I'm going to create two new posts here we don't need to watch me type this out this is going to create uh two posts that we can then go ahead and verify against here's where it gets fun now we can use this server to make a mock call out to the uh rest API so we're going to basically say hey when actually we don't even do that so we're gonna say server do expect and we're going to say we want a request to um the uh that looks pretty good right uh so one thing I'm going to need here is an object mapper uh the object mapper is part of Jackson and it'll just help us kind of turn that um particular list of posts into some Json that we could pass to us so this looks pretty good let's see and expect so these are going to need to be imported all right so we're request so basically now what we're looking at is the uh expected URI um so anytime a call is me to this particular URI we want to mock that out and what we're going to do is respond with uh a success so a 200 and we're going to use the object mapper to write that data so we're going to get that Json back and we can see the media type is application Json right so uh we're going to have to catch this exception here we can throw this um so that's a Json processing exception so now we have our given which is our list of posts we have our when hey when this happens then I expect this to happen and all I want to do here is go ahead and call that so I'm going to say um my post client right I want to find all and when that happens we're going to get let back a list of posts and so now I can say assert equals and I can say hey we should get it back too right so that is our test and let's go ahead and run this and see if that works and it does so that passes so great so now we have a way to kind of mock that out and go ahead and not have to worry about hitting that live service now again there might be a scenario where you want an integration test to actually hit that service but in this case hey when we call the find all it's not actually going out to the service it's going to mock that out now I will say um there's a couple bit a couple differences that or a couple things that threw me off one the expected URI if you're using something like the rest template because again this this annotation right here supports the rest template and the rest client when you use the rest template if you see examples online that URI is just the URI so slash posts um when it comes to the client you need the full URI here so we have the base URL plus the URI you need to make sure you do that that threw me off number one number two there is an issue if you try and use a different well if you try and use a specific jdk HTTP um client so what do I mean by that uh we did this in a different uh separate video but you can come in here and say I want a jdk client HTTP request Factor and this will replace the um default HTTP client underneath the hood which is the HTTP URL connection and we could say we want to swap that out with this um so if we go ahead and do that and we try to run our test again basically something happens here where it doesn't use the mock server and it goes out and it actually gets all 100 so it's not actually mocking it it's not using our mock data there it's actually going out to the service making that call and that's why this fails so just a little bit of a gotcha I put that in the read me as well in case you switch to the jdk uh HTTP client because that's something I often do uh there is an issue on GitHub I think I put that in the release notes as well so just be on the lookout for that so we just did one method but uh this will work for all of the methods so we can write tests uh against all of our methods you can go in and write a test to find a single one to create one to update delete Etc uh this will work for all the methods and I think this is a really nice place to start I know there's uh conversations around like when should we mock when should we not again I'll leave that up to you this is in the case of I don't want to make an actual integration test to to talk to that service and in that case this at uh rest client test annotation is really good again this is a slice test so it's loading only the bits that are relevant to this test which is important because if you have a larger application you don't want to load up the entire application context and run your tests against it uh this ends up being very fast so I enjoy this one so hey uh I thought this was a good little exercise in how to test our rest clients if you found it useful I'd appreciate a thumbs up subscribe to the channel and as always friends happy [Music] coding here we go here we go
Info
Channel: Dan Vega
Views: 5,980
Rating: undefined out of 5
Keywords: dan vega, spring framework, java, spring boot, rest template, rest client, http, spring boot test, rest client test
Id: jhhi03AIin4
Channel Id: undefined
Length: 12min 0sec (720 seconds)
Published: Fri Jan 26 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.