This is the fifth in the Spring Boot series. This time, I will explain ** how to stub the source ** with a little change from the past.
I think that the most common ones are ** Mockito in UT and mocking by wiremock in FT **. If you bootRun, each mock will not work, so you may have trouble with HTTP communication failure or not being able to connect to the DB.
If you make it a stub by the method I will introduce from now on, ** It is possible to use stubs in some environments and hit the actual API only in the environment where the opposite API exists **.
I hope it will be helpful for those in need! !!
What kind of method is used to stub the source? ** Register the stub class with the same name as the class you want to stub in the DI container, add @Primary and replace it **, I will do that.
It appears several times in my article, but I use the ** Zip Code Search API **. As the name suggests, it is an API that returns address information in the response body when you request by putting the zip code on the query parameter.
For the implementation, see here. Let's bootRun and hit what kind of result will be returned.
First, try requesting an existing address. You have successfully obtained the zip code and prefecture code. The normal system looks like this.
So what if you request an address that doesn't exist?
Of course, if you type a zip code that doesn't exist, you'll get an empty response **.
… So what if you had to release this app in an environment where the ** zip code search API doesn't exist? ** ** Needless to say, no matter what zip code you request, you'll get a 404 error ** and it's useless.
Let's make a stub and deal with it ** for such a case! !!
I think it's easier to imagine while looking at the implementation class. First, put the implementation class.
MockClient.java
@Configuration // (1)
public class MockClient {
@Bean // (1)
@Primary // (1)
public GetAddressApiClient mockGetAddressApiClient(RestTemplateBuilder restTemplateBuilder,
ResponseHandlerInterceptor interceptor) {
return new MockGetAddressApiClient(restTemplateBuilder, interceptor);
}
static class MockGetAddressApiClient extends GetAddressApiClient { // (2)
MockGetAddressApiClient(RestTemplateBuilder restTemplateBuilder,
ResponseHandlerInterceptor interceptor) {
super(restTemplateBuilder, interceptor);
}
@Override
public GetAddressApiResponse request(String zipCode) {
return new GetAddressApiResponse( // (3)
"200",
"",
Arrays.asList(
new GetAddressApiResponse.Result(
"zipcode",
"prefcode",
"address1",
"address2",
"address3",
"kana1",
"kana2",
"kana3"
),
new GetAddressApiResponse.Result(
"zipcode",
"prefcode",
"address1",
"address2",
"address3",
"kana1",
"kana2",
"kana3"
)
)
);
}
}
}
I will explain each point!
@ Configuration
+@ Primary (@Bean)
Bean definition by annotation is possible in Spring, and stub class is registered in DI container with @ Configuration
+ @ Bean
used at that time.
However, at this time, since the real GetAddressApiClient
is also registered, ** there will be two beans with the same name, and Spring will raise an exception. ** **
Use ** @ Primary
** to get around it!
As a result, the one with @Primary
will be given priority.
In other words, ** the stub class will always be used **.
Next, create the stub class itself. As mentioned above, this time it is necessary to register the bean with the same type as the real class. To do this, ** create a stub class by inheriting the real class **. It's relatively important.
super
.@Override
the method and define the return valueThe rest is the definition of the return value.
In this case, override the request
method and return any return value you like.
Let's bootRun and hit. Since the response written in the stub is returned, It seems that it has been successfully made into a stub!
… But here is another question. ** "This stub always works, so maybe the real class doesn't work?" ** …That's right. This time, on the contrary, it has become an application that only works with stubs.
So ** Let's make it possible to use the real thing and the stub properly for each environment! !! ** **
** Add @Profile
to the stub class **.
As a result, ** the stub class will be DI-registered only in the specified environment, and the stub class will not be DI-registered in the unspecified environment (≒ real works) **.
MockClient.java
@Configuration
@Profile("dev")
public class MockClient {
//abridgement
}
In the above case, it will be a stub class only in the dev environment
, and the real Client class will work in other environments!
Thank you for watching until the end! When I looked it up, I found that there weren't many articles like this, so I hope it helps someone!
We welcome your comments and comments!
Recommended Posts