Class ResourceClient<T>
- Type Parameters:
T- resource type
For example: client.method(mock -> mock.restMethod("queryParam").asVoid()))
It would resolve target HTTP method, target path (from method annotation) and apply query parameter
(because of not null value provided for method parameter, annotated with QueryParam).
This simplifies test request building, making it almost refactoring-safely. Also, it makes simple navigation from test to called resource method.
It is still possible to call methods by path with generic methods like TestClient.get(String, Class, Object...)
or TestClient.buildGet(String, Object...).
Wrapper for JerseyClient. Jersey client is a general-purpose client and
this api specialized for tests. Also, the jersey request builder is split into two parts: target and request.
This api unifies it into a single step, for simplicity.
The "defaults" concept: some values (query params, headers, cookies, etc.) could be configured once
for all client requests (this is usually handy for tests, for example, to unify authorization).
See "default*" methods for details (for example, TestClientDefaults.defaultHeader(String, Object)).
Defaults could be cleared with TestClientDefaults.reset() or printed into console with TestClientDefaults.printDefaults()
There are multiple ways to perform a request:
- Raw jersey target
TestClient.target(String, Object...)(defaults does not apply!) - Raw jersey builder
TestClient.request(String, Object...)with applied defaults - Shortcut methods (to execute a general call and receive the result) like
TestClient.get(String, Class, Object...),TestClient.post(String, Object, Class, Object...), etc. - Shortcut builders (for additional request configurations) like
TestClient.buildGet(String, Object...),TestClient.buildPost(String, Object, Object...), etc - Special builder for forms (multipart and urlencoded):
TestClient.buildForm(String, Object...) - General builder:
TestClient.build(String, String, Object, Object...)
All "build*" methods return a custom builder object with all the same configuration options as the original
jersey client builder, but all gathered in one place (easier to use). This builder could return either
directly mapped object (with
TestClientRequestBuilder.as(Class)) or a special response object wrapper with pre-defined assertions
to simplify testing (TestClientRequestBuilder.expectSuccess(Integer...) or
TestClientRequestBuilder.expectFailure(Integer...) or without response validation
TestClientRequestBuilder.invoke()).
All methods support (optional) string format for a path. For example, the call
client.get("/entity/%s", Entity.class, 12) will use "/entity/12/" as target path.
Examples:
TestClient client;
// jersey api (no defaults applied)
Entity res = client.target("/some/path").request().get(Entity.class);
// jersey api (with defaults applied)
Entity res = client.request("/some/path").get(Entity.class);
// shortcut method
Entity res = client.get("/some/path", Entity.class);
// shortcut with composite entity type (note diamond operator usage):
List<Entity> res = client.get("/some/path", new GenericType<>() {});
// builder method
Entity res = client.buildGet("/some/path")
.header("Something", "Value")
.invoke(Entity.class);
// builder with response assertions ():
Entity res = client.buildGet("/some/path")
// error thrown if response is not success with (optional) exact status validation
.expectSuccess(200)
// assertion error if value will not match or cookie absent
.assertCookie("Name", "Value")
// assertion error if value will not match or header absent
.assertHeader("Something", "Value")
// map entity
.as(EntityClass)
// defaults demo:
client.defaultHeader("Authorization", "Bearer 1234567890");
// request would contain the default header
Entity res = client.get("/some/path", Entity.class);
The main idea behind chained assertions is redundant variables avoidance in test.
Note that builder method return AutoCloseable object (same as Response)
because a response object must be closed (response is closed when response body is consumed).
Because of this your IDE could warn you that the result of, for example, TestClientRequestBuilder.invoke()
must be used with "try-with-resources" statement. In most cases, you can ignore this warning as guicey tracks all
such wrapped responses and would close it after a test application shutdown.
Builder api does not hide jersey api: if required, you can modify target directly with
TestClientDefaults.defaultPathConfiguration(java.util.function.Function) or jersey builder with
TestClientDefaults.defaultRequestConfiguration(java.util.function.Consumer).
Builder supports jersey client properties (TestClientDefaults.defaultProperty(String, Object)) and extensions
TestClientDefaults.defaultRegister(Class) and TestClientDefaults.defaultRegister(Object). As an example, property could be used to
disable redirects (TestClientRequestBuilder.notFollowRedirects() which is used automatically by
TestClientRequestBuilder.expectRedirect(Integer...)). For a custom extension example see
TestClientRequestBuilder.noBodyMappingForVoid() (which is used automatically by
TestClientRequestBuilder.asVoid() to ignore response body mapping for void requests).
The client could be used to build sub-clients. In this case all defaults will be inherited from the parent client. For example, we have a general rest client, but our particular test would check only one resource. In this case we can create a sub-client for the resource path to avoid it in all method calls:
TestClient api;
TestClient subRest = api.subClient("/resource/{param}/path")
.defaultPathParam("param", 123);
// this would call "/resource/123/path/method"
Entity res = subRest.get("/method", Entity.class);
TestClient is a general client class, but there are special client classes for rest (extending it):
ResourceClient (could be obtained from the root) and
object (which is also a test client))
- Since:
- 18.09.2025
-
Field Summary
Fields inherited from class ru.vyarus.dropwizard.guice.test.client.builder.TestClientDefaults
defaults -
Constructor Summary
ConstructorsConstructorDescriptionResourceClient(@Nullable Supplier<jakarta.ws.rs.client.WebTarget> root, @Nullable TestRequestConfig defaults, Class<T> resource) Create a resource client. -
Method Summary
Modifier and TypeMethodDescriptionCreate request builder from resource method: automatic configuration of targe path and http method selection.Create request builder from resource method: automatic configuration of targe path and http method selection.Create request builder from resource method: automatic configuration of targe path and http method selection.Create request builder from resource method: automatic configuration of targe path and http method selection.Configure request from resource method call.Configure a request from the resource method call.multipartMethod(MultipartAwareCaller<T> caller) The same asmethod(ru.vyarus.dropwizard.guice.url.util.Caller, Object), but provides a helper utility to easily stub multipart parameters (so these values could be used for request configuration).<R> ResourceClient<R>restClient(Class<R> resource) Create a new sub-client for a specified resource class (appends a resource path, obtained fromPathannotation, to the current client path).<R> ResourceClient<R>subResourceClient(Caller<T> caller, Class<R> subResource) Create a sub client for the sub-resource.toString()Methods inherited from class ru.vyarus.dropwizard.guice.test.client.TestClient
asRestClient, build, buildDelete, buildForm, buildGet, buildPatch, buildPost, buildPut, delete, delete, delete, get, get, get, getBaseUri, getEntity, getRoot, patch, patch, patch, post, post, post, put, put, put, request, subClient, subClient, subClient, subResourceClient, targetMethods inherited from class ru.vyarus.dropwizard.guice.test.client.builder.TestClientDefaults
defaultAccept, defaultAccept, defaultCacheControl, defaultCacheControl, defaultCookie, defaultCookie, defaultCookie, defaultDebug, defaultEncoding, defaultFormDateFormat, defaultFormDateFormatter, defaultFormDateTimeFormatter, defaultHeader, defaultHeader, defaultHeader, defaultHeader, defaultLanguage, defaultLanguage, defaultMatrixParam, defaultMatrixParam, defaultPathConfiguration, defaultPathParam, defaultPathParam, defaultProperty, defaultProperty, defaultQueryParam, defaultQueryParam, defaultRegister, defaultRegister, defaultRegister, defaultRequestConfiguration, getDefaults, hasDefaultAccepts, hasDefaultCacheControl, hasDefaultCookies, hasDefaultCustomConfigurators, hasDefaultEncodings, hasDefaultExtensions, hasDefaultFormDateFormatter, hasDefaultHeaders, hasDefaultLanguages, hasDefaultMatrixParams, hasDefaultPathParams, hasDefaultProperties, hasDefaultQueryParams, hasDefaults, isDebugEnabled, printDefaults, reset, self
-
Constructor Details
-
ResourceClient
public ResourceClient(@Nullable Supplier<jakarta.ws.rs.client.WebTarget> root, @Nullable TestRequestConfig defaults, Class<T> resource) Create a resource client.- Parameters:
root- root pathdefaults- defaultsresource- resource type
-
-
Method Details
-
multipartMethod
The same asmethod(ru.vyarus.dropwizard.guice.url.util.Caller, Object), but provides a helper utility to easily stub multipart parameters (so these values could be used for request configuration).For the most common case
post(@FormDataParam("file") InputStream stream, @FormDataParam("file") FormDataContentDisposition fileDetail):
.multipartMethod((instance, multipart) -> instance .post(multipart.fromClasspath("/some.txt"), multipart.disposition("file", "some.txt"))it could be a single field:
post(@FormDataParam("file") FormDataBodyPart file):
or to get file from classpath:multipartMethod((instance, multipart) -> instance .post(multipart.filePart("/some.txt"))
.multipartMethod((instance, multipart) -> instance .post(multipart.streamPart("/some.txt"))There might be multiple files for the same field
post(@FormDataParam("file") List<FormDataBodyPart> file):
.multipartMethod((instance, multipart) -> instance .post(Arrays.asList( multipart.filePart("/some.txt"), multipart.filePart("/other.txt")))When the method only accepts content-disposition mapping, it would be also used with en empty file content (as file content is not required, preserve available data):
post(@FormDataParam("file") FormDataContentDisposition file)
.multipartMethod((instance, multipart) -> instance .post(multipart.disposition("file", "some.txt"))The method parameter could be a complete multipart object (with all fields inside):
post(FormDataMultiPart multiPart): for such cases there is a special builder:multipartMethod((instance, multipart) -> instance .post(multipart.multipart() .field("foo", "val") .file("file1", "/some.txt) .stream("file2", "/other.txt) .build())It is not required to specify all parameters: you may use null on any of them (it is just a one way to configure request).
Note that it is not required to declare fields like this! You can always prepare entity manually and use caller with body
method(ru.vyarus.dropwizard.guice.url.util.Caller, Object).- Parameters:
caller- multipart method caller- Returns:
- builder instance for chained calls
-
method
Configure request from resource method call. Seemethod(ru.vyarus.dropwizard.guice.url.util.Caller, Object).- Parameters:
caller- resource method caller- Returns:
- pre-configured request builder instance
-
method
Configure a request from the resource method call. The main idea here: request could be configured automatically from the resource method annotations. Arguments for annotated parameters could be used to provide default values.- target path resolved from method
Path - target method resolved from method annotation (like
GET) - analyze provided method arguments to get values for annotated parameters (like
QueryParam,PathParam, etc.) - build form body from not null
FormParamandFormDataParam
All these configuration values could be overridden with a received builder. Also, put null on arguments that should not be configured automatically.
Note that by default requests are logged, so the correctness of the target url could be verified easily.
Might also include sub resource call, if sub resource locator method returns resource instance:
resource.sub(args).method(args)- Parameters:
caller- resource method callerbody- request body (form param ignored for POST if body provided)- Returns:
- pre-configured request builder instance
- target path resolved from method
-
method
Create request builder from resource method: automatic configuration of targe path and http method selection.For more advanced defaults configuration see
method(ru.vyarus.dropwizard.guice.url.util.Caller)(it will also apply configuration by provided method parameter values).If multiple methods selected, will select method without arguments. If there is no matching no-args method found throws exception (about multiple methods found). This no-args behavior is required to comply with arguments-based search (it would be otherwise impossible to search for no-args method).
- Parameters:
method- method name to call (there must be only one such method)- Returns:
- request builder instance
- Throws:
IllegalStateException- if unique method not found
-
method
Create request builder from resource method: automatic configuration of targe path and http method selection.For more advanced defaults configuration see
method(ru.vyarus.dropwizard.guice.url.util.Caller)(it will also apply configuration by provided method parameter values).- Parameters:
method- method name to call (there must be only one such method)- Returns:
- request builder instance
-
method
Create request builder from resource method: automatic configuration of targe path and http method selection.For more advanced defaults configuration see
method(ru.vyarus.dropwizard.guice.url.util.Caller, Object)(it will also apply configuration by provided method parameter values).- Parameters:
method- method name to call (there must be only one such method)body- (optional) request body (everything exceptEntityconverted to JSON)- Returns:
- request builder instance
- Throws:
IllegalStateException- if jersey annotations aren't found on the method
-
method
Create request builder from resource method: automatic configuration of targe path and http method selection.For more advanced defaults configuration see
method(ru.vyarus.dropwizard.guice.url.util.Caller, Object)(it will also apply configuration by provided method parameter values).If multiple methods selected, will select the method without arguments. If there is no matching no-args method found, throws exception (about multiple methods found).
- Parameters:
method- method name to call (there must be only one such method)body- (optional) request body (everything exceptEntityconverted to JSON)- Returns:
- request builder instance
- Throws:
IllegalStateException- if unique method not found
-
restClient
Description copied from class:TestClientCreate a new sub-client for a specified resource class (appends a resource path, obtained fromPathannotation, to the current client path). Method is useful when generic rest path must be "typed" with a resource type (to be able to call resource methods directly).In case of sub-resources, use
TestClient.subResourceClient(String, Class, Object...)to properly specify sub-resource mapping path (from lookup method):ResourceClient rest = client.subResourceClient("path", SubResource.class). IMPORTANT: this is NOT THE SAME:client.subClient("path").restClient(SubResource.class)because "restClient()" call would append path from resource, which is ignored for sub resources!.Defaults could be used to declare path parameter values:
ResourceClient rest = client.restClient(Resource.class).defaultPathParam("param", "value")where a resource class path is like "/some/{param}/path". With the default path param, there would be no need to declare it for each request call.All defaults, configured for the current client, will be inherited in a sub-client. If this is not required, just clean defaults after creation:
client.subClient(ResClass.class).reset().- Overrides:
restClientin classTestClient<TestClient<?>>- Type Parameters:
R- resource type- Parameters:
resource- resource class one to build a path for- Returns:
- resource client (with a resource path, relative to the current client path)
-
subResourceClient
Create a sub client for the sub-resource. Sub resource path is resolved through the called locator method. Note: multiple locator methods could be called at once!- Type Parameters:
R- sub-resource type- Parameters:
caller- locator method(s) callersubResource- sub-resource type- Returns:
- sub-resource client
-
getResourceType
- Returns:
- resource type
-
toString
- Overrides:
toStringin classTestClient<TestClient<?>>
-