Spring Cloud Contract Stub Runner : how to configure Wiremock server? - wiremock

package com.example.stubrunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.contract.stubrunner.server.EnableStubRunnerServer;
import org.springframework.cloud.contract.wiremock.WireMockConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
#EnableStubRunnerServer
public class StubRunnerApplication {
public static void main(String[] args) {
SpringApplication.run(StubRunnerApplication.class, args);
}
#Bean
public WireMockConfigurationCustomizer optionsCustomizer() {
WireMockConfigurationCustomizer customizer = new WireMockConfigurationCustomizer() {
#Override
public void customize(com.github.tomakehurst.wiremock.core.WireMockConfiguration config) {
config.jettyHeaderBufferSize(16384);
}
};
return customizer;
}
}
Above customizer bean does not seem to have any effect. This feature has not much documentation. With security token headers Wiremock's (jettty) default value is just too little.
I used start.spring.io with (current) defaults: spring boot 2.5.5. and spring cloud Hoxton.SR3.
java -jar wiremock-standalone-2.26.3.jar --jetty-header-buffer-size 16384
works just fine.
EDIT :
package com.example.wiremockrunnerlatest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.contract.stubrunner.server.EnableStubRunnerServer;
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
#SpringBootApplication
#EnableStubRunnerServer
#AutoConfigureStubRunner(httpServerStubConfigurer = HeaderSizeConfigurer.class)
public class WiremockRunnerLatestApplication {
public static void main(String[] args) {
SpringApplication.run(WiremockRunnerLatestApplication.class, args);
}
}
... and then :
public class HeaderSizeConfigurer extends WireMockHttpServerStubConfigurer {
#Override
public WireMockConfiguration configure(WireMockConfiguration httpStubConfiguration, HttpServerStubConfiguration httpServerStubConfiguration) {
return httpStubConfiguration.jettyHeaderBufferSize(16384);
}
}

Have you tried using #AutoConfigureStubRunner annotation?
Just add below annotation in your tests:
#AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.CLASSPATH,
ids = "com.org:servicename:+:stubs")
Here stubsmode is classpath which means that stubs would be available in classpath.
to do that add:
testCompile("com.org:servicename:+:stubs") { transitive = false }
in your build if your using gradle or add equivalient from maven.
This will download the application automatically from remote and configures the wiremock server for stubs to be available.
complete configuration to run a spring boot test is like:
#RunWith(SpringRunner.class)
#SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.MOCK,
classes = HiltiIntegrationApplication.class)
#AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.CLASSPATH,
ids = "com.ict:organization-management:+:stubs")
#DirtiesContext
Hope this helps!

Related

Why does JobBuilder says could not autowire?

I am following this Udemy course(Batch Processing with Spring Batch & Spring Boot
) for Spring Batch. In the course JBF(JobBuilderFactory) is depracated so I googled what to use instead and it says use JobBuilder.
Right now jobBuilder and stepBuilder are underlined red and says could not autowired.
package com.example.springbatch;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
//1st step
#EnableBatchProcessing
//2nd //use of this?
#ComponentScan("com.example.config") //job and steps will go in this packet
public class SpringBatchApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBatchApplication.class, args);
}
}
package com.example.config;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration //add annot
public class SampleJob { //3rd creating first samp job
//5th Create the job, spring batch provides one class - job builder. And create the obj named jobBuilder
#Autowired
private JobBuilder jobBuilder;
#Autowired
private StepBuilder stepBuilder;
#Bean //4th define #Bean for the first job
public Job firstJob() { //Job(interface) imports core.Job
//6th use
return jobBuilder.get("First Job") //use get First Job is 1st job name
.start(firstStep()) //Inside the start, pass in your step. Job can hava single or multiple step
.build();
}
#Bean //7th Adding the Step interface. Autowire it as well.
Step firstStep() {
return stepBuilder.get("First Step")
.tasklet(firstTask()) //Will need to call Tasklet.
.build(); //call build to create the step.
}
//8th
private Tasklet firstTask() {
return new Tasklet() {
#Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println("This is first tasklet step");
return RepeatStatus.FINISHED; //need this
}
};
}
}
I tried to search on google and this is suppose to print System.out.println("This is first tasklet step");
The course is probably using Spring Batch 4. In Spring Batch 5, those builder factories were deprecated for removal and are not exposed as beans in the application context by the #EnableBatchProcessing annotation. Here is the relevant section in the migration guide about that: JobBuilderFactory and StepBuilderFactory bean exposure/configuration.
The typical migration path from v4 to v5 in that regard is as follows:
// Sample with v4
#Configuration
#EnableBatchProcessing
public class MyJobConfig {
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Bean
public Job myJob(Step step) {
return this.jobBuilderFactory.get("myJob")
.start(step)
.build();
}
}
// Sample with v5
#Configuration
#EnableBatchProcessing
public class MyJobConfig {
#Bean
public Job myJob(JobRepository jobRepository, Step step) {
return new JobBuilder("myJob", jobRepository)
.start(step)
.build();
}
}

How to create custom retry logic for Spring Datasource?

I'm connecting to an Azure SQL database and my next task is to create custom retry logic when a connection has failed. I would like the retry logic to run both on startup (if needed) as well as any time there's a connection failure while the app is running. I did a test where I removed the IP restrictions from my app and that then caused an exception in my application (as excepted). I'd like to handle when that exception is thrown so that I can trigger a job that verifies both the app and the server are configured correctly. I'm looking for a solution where I can handle these exceptions and retry the DB transaction?
DataSource Config
#Bean
#Primary
public DataSource dataSource() {
return DataSourceBuilder
.create()
.username("username")
.password("password")
.url("jdbc:sqlserver://contoso.database.windows.net:1433;database=*********;user=******#*******;password=*****;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;")
.driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
.build();
}
application.properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
spring.jpa.show-sql=true
logging.level.org.springframework.web: ERROR
logging.level.org.hibernate: ERROR
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=1
spring.datasource.tomcat.test-on-borrow=true
spring.jpa.hibernate.ddl-auto=update
The following code may help you create your retry logic for a data source on Spring Boot:
package com.example.demo;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.AbstractDataSource;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
#SpringBootApplication
#EnableRetry
public class DemoApplication {
#Order(Ordered.HIGHEST_PRECEDENCE)
private class RetryableDataSourceBeanPostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof DataSource) {
bean = new RetryableDataSource((DataSource)bean);
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public BeanPostProcessor dataSouceWrapper() {
return new RetryableDataSourceBeanPostProcessor();
}
}
class RetryableDataSource extends AbstractDataSource {
private DataSource delegate;
public RetryableDataSource(DataSource delegate) {
this.delegate = delegate;
}
#Override
#Retryable(maxAttempts=10, backoff=#Backoff(multiplier=2.3, maxDelay=30000))
public Connection getConnection() throws SQLException {
return delegate.getConnection();
}
#Override
#Retryable(maxAttempts=10, backoff=#Backoff(multiplier=2.3, maxDelay=30000))
public Connection getConnection(String username, String password)
throws SQLException {
return delegate.getConnection(username, password);
}
}
Not sure what you deem custom but, there is an out-of-the-box option with Spring boot and Aspectj by leveraging the pom.xml in the mavern project, as spring-retry depends on Aspectj:
Add the following dependencies in your project pom.xml:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${version}</version>
</dependency>
And then add the #EnableRetry annotation to your code:
package com.example.springretry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
#EnableRetry
#SpringBootApplication
public class SpringRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRetryApplication.class, args);
}
}
The Spring retry module example can be found here: https://howtodoinjava.com/spring-boot2/spring-retry-module/

Spring Boot Rest : Error 404 not found when posting JSON via Postman

I am trying to invoke a POST service via Postman. My application is running on embedded tomcat server. However when I try to invoke the service, the error I get is "No mapping found for HTTP request with URI [/findrouting] in DispatcherServlet with name 'dispatcherServlet'"
It is not even recognizing http:localhost:8080/
RoutingRequest and RoutingResponse are the POJOs with getters and setters.
Am I missing something here. I did check lots of examples but didn't find any solution to my problem.
Please see my code below :
package com.ab.hello.ambassador.server;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(AmbassadorApplication.class, args);
System.out.println("List of Beans instantiated");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
}
package com.ab.hello.ambassador.server.controller;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.dp.connect.ambassador.server.RoutingRequest;
import com.dp.connect.ambassador.server.RoutingResponse;
#RestController
public class ApplicationController {
#RequestMapping("/")
public String index() {
return "Spring Boot POC Welcomes You!";
}
#RequestMapping(method = POST, value = "/findrouting", consumes = { APPLICATION_JSON_VALUE }, produces = {
APPLICATION_JSON_VALUE })
public RoutingResponse findRoute(#RequestBody RoutingRequest request) throws Exception {
// some business logic that would return response; as of now I have set it to null
RoutingResponse response = null;
return response;
}
}
Thanks for your time. After struggling for quite a long time. I figured out this piece of code. Added annotation #EnableWebMvc. This solved my problem.
#SpringBootApplication
#EnableWebMvc
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Try to define the path in your controller:
#RestController
#RequestMapping("/")
public class ApplicationController {
#RequestMapping
public String index() {
return "Spring Boot POC Welcomes You!";
}
#RequestMapping(method = POST, value = "/findrouting", consumes = { APPLICATION_JSON_VALUE }, produces = {
APPLICATION_JSON_VALUE })
public RoutingResponse findRoute(#RequestBody RoutingRequest request) throws Exception {
// some business logic that would return response; as of now I have set it to null
RoutingResponse response = null;
return response;
}
}
Change the below line
ApplicationContext ctx = SpringApplication.run(AmbassadorApplication.class, args);
with
ApplicationContext ctx = SpringApplication.run(Application.class, args);
according to spring docs , seems need to Override a config method:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}

"404 Not Found" when viewing swagger api-docs when using swagger-springmvc (now springfox)

I am trying to configure swagger in my spring project, but hitting Hitting "http://localhost:8080/api-docs" says "404 Not Found".
Maven Dependency
<dependency>
<groupId>com.mangofactory</groupId>
<artifactId>swagger-springmvc</artifactId>
<version>0.8.2</version>
</dependency>
SwaggerConfig.java File
package com.ucap.swagger;
import com.mangofactory.swagger.configuration.JacksonScalaSupport;
import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.configuration.SpringSwaggerModelConfig;
import com.mangofactory.swagger.configuration.SwaggerGlobalSettings;
import com.mangofactory.swagger.core.DefaultSwaggerPathProvider;
import com.mangofactory.swagger.core.SwaggerApiResourceListing;
import com.mangofactory.swagger.core.SwaggerPathProvider;
import com.mangofactory.swagger.scanners.ApiListingReferenceScanner;
import com.wordnik.swagger.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
#Configuration
#ComponentScan(basePackages = "com.mangofactory.swagger")
public class SwaggerConfig {
public static final List<String> DEFAULT_INCLUDE_PATTERNS = Arrays.asList("/news/.*");
public static final String SWAGGER_GROUP = "mobile-api";
#Value("${app.docs}")
private String docsLocation;
#Autowired
private SpringSwaggerConfig springSwaggerConfig;
#Autowired
private SpringSwaggerModelConfig springSwaggerModelConfig;
/**
* Adds the jackson scala module to the MappingJackson2HttpMessageConverter registered with spring
* Swagger core models are scala so we need to be able to convert to JSON
* Also registers some custom serializers needed to transform swagger models to swagger-ui required json format
*/
#Bean
public JacksonScalaSupport jacksonScalaSupport() {
JacksonScalaSupport jacksonScalaSupport = new JacksonScalaSupport();
//Set to false to disable
jacksonScalaSupport.setRegisterScalaModule(true);
return jacksonScalaSupport;
}
/**
* Global swagger settings
*/
#Bean
public SwaggerGlobalSettings swaggerGlobalSettings() {
SwaggerGlobalSettings swaggerGlobalSettings = new SwaggerGlobalSettings();
swaggerGlobalSettings.setGlobalResponseMessages(springSwaggerConfig.defaultResponseMessages());
swaggerGlobalSettings.setIgnorableParameterTypes(springSwaggerConfig.defaultIgnorableParameterTypes());
swaggerGlobalSettings.setParameterDataTypes(springSwaggerModelConfig.defaultParameterDataTypes());
return swaggerGlobalSettings;
}
/**
* API Info as it appears on the swagger-ui page
*/
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"News API",
"Mobile applications and beyond!",
"https://helloreverb.com/terms/",
"matt#raibledesigns.com",
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0.html"
);
return apiInfo;
}
/**
* Configure a SwaggerApiResourceListing for each swagger instance within your app. e.g. 1. private 2. external apis
* Required to be a spring bean as spring will call the postConstruct method to bootstrap swagger scanning.
*
* #return
*/
#Bean
public SwaggerApiResourceListing swaggerApiResourceListing() {
//The group name is important and should match the group set on ApiListingReferenceScanner
//Note that swaggerCache() is by DefaultSwaggerController to serve the swagger json
SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(springSwaggerConfig.swaggerCache(), SWAGGER_GROUP);
//Set the required swagger settings
swaggerApiResourceListing.setSwaggerGlobalSettings(swaggerGlobalSettings());
//Use a custom path provider or springSwaggerConfig.defaultSwaggerPathProvider()
swaggerApiResourceListing.setSwaggerPathProvider(apiPathProvider());
//Supply the API Info as it should appear on swagger-ui web page
swaggerApiResourceListing.setApiInfo(apiInfo());
//Global authorization - see the swagger documentation
swaggerApiResourceListing.setAuthorizationTypes(authorizationTypes());
//Every SwaggerApiResourceListing needs an ApiListingReferenceScanner to scan the spring request mappings
swaggerApiResourceListing.setApiListingReferenceScanner(apiListingReferenceScanner());
return swaggerApiResourceListing;
}
#Bean
/**
* The ApiListingReferenceScanner does most of the work.
* Scans the appropriate spring RequestMappingHandlerMappings
* Applies the correct absolute paths to the generated swagger resources
*/
public ApiListingReferenceScanner apiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner = new ApiListingReferenceScanner();
//Picks up all of the registered spring RequestMappingHandlerMappings for scanning
apiListingReferenceScanner.setRequestMappingHandlerMapping(springSwaggerConfig.swaggerRequestMappingHandlerMappings());
//Excludes any controllers with the supplied annotations
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig.defaultExcludeAnnotations());
//
apiListingReferenceScanner.setResourceGroupingStrategy(springSwaggerConfig.defaultResourceGroupingStrategy());
//Path provider used to generate the appropriate uri's
apiListingReferenceScanner.setSwaggerPathProvider(apiPathProvider());
//Must match the swagger group set on the SwaggerApiResourceListing
apiListingReferenceScanner.setSwaggerGroup(SWAGGER_GROUP);
//Only include paths that match the supplied regular expressions
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
return apiListingReferenceScanner;
}
/**
* Example of a custom path provider
*/
#Bean
public ApiPathProvider apiPathProvider() {
ApiPathProvider apiPathProvider = new ApiPathProvider(docsLocation);
apiPathProvider.setDefaultSwaggerPathProvider(springSwaggerConfig.defaultSwaggerPathProvider());
return apiPathProvider;
}
private List<AuthorizationType> authorizationTypes() {
ArrayList<AuthorizationType> authorizationTypes = new ArrayList<>();
List<AuthorizationScope> authorizationScopeList = newArrayList();
authorizationScopeList.add(new AuthorizationScope("global", "access all"));
List<GrantType> grantTypes = newArrayList();
LoginEndpoint loginEndpoint = new LoginEndpoint(apiPathProvider().getAppBasePath() + "/user/authenticate");
grantTypes.add(new ImplicitGrant(loginEndpoint, "access_token"));
return authorizationTypes;
}
#Bean
public SwaggerPathProvider relativeSwaggerPathProvider() {
return new ApiRelativeSwaggerPathProvider();
}
private class ApiRelativeSwaggerPathProvider extends DefaultSwaggerPathProvider {
#Override
public String getAppBasePath() {
return "/";
}
#Override
public String getSwaggerDocumentationBasePath() {
return "/api-docs";
}
}
}
ApiPathProvider.java file
package com.ucap.swagger;
import com.mangofactory.swagger.core.SwaggerPathProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.ServletContext;
public class ApiPathProvider implements SwaggerPathProvider {
private SwaggerPathProvider defaultSwaggerPathProvider;
#Autowired
private ServletContext servletContext;
private String docsLocation;
public ApiPathProvider(String docsLocation) {
this.docsLocation = docsLocation;
}
#Override
public String getApiResourcePrefix() {
return defaultSwaggerPathProvider.getApiResourcePrefix();
}
public String getAppBasePath() {
return UriComponentsBuilder
.fromHttpUrl(docsLocation)
.path(servletContext.getContextPath())
.build()
.toString();
}
#Override
public String getSwaggerDocumentationBasePath() {
return UriComponentsBuilder
.fromHttpUrl(getAppBasePath())
.pathSegment("api-docs/")
.build()
.toString();
}
#Override
public String getRequestMappingEndpoint(String requestMappingPattern) {
return defaultSwaggerPathProvider.getRequestMappingEndpoint(requestMappingPattern);
}
public void setDefaultSwaggerPathProvider(SwaggerPathProvider defaultSwaggerPathProvider) {
this.defaultSwaggerPathProvider = defaultSwaggerPathProvider;
}
}
Also, there is a property file in resources folder which contains:
app.docs=http://localhost:8080
When I am hitting "http://localhost:8080/api-docs" it neither gives any result nor any error, On google Rest the response code is 404.
Please help me on this.
The version that you're using (0.8.2) is a very old version of springfox. You should try and move to the latest released version, which is 2.0.
To answer your questions specifically.
Move to the most recent pre-2.0 version. Change the version of swagger-spingmvc in your pom to 1.0.2
The swagger configuration is vastly simplified in later releases. Change your SwaggerConfig to look like this.
#Configuration
//Hard to tell without seeing all your configuration, but optionally,
//add EnableWebMvc annotation in case its not working
#EnableWebMvc
#EnableSwagger
//Assuming your controllers are in this package
#ComponentScan(basePackages = "com.ucap.swagger")
public class SwaggerConfig {
public static final List<String> DEFAULT_INCLUDE_PATTERNS
= Arrays.asList("/news/.*");
//Unless you specifically want this group, I would recommend ignoring this
public static final String SWAGGER_GROUP = "mobile-api";
#Autowired
private SpringSwaggerConfig springSwaggerConfig;
#Bean
public SwaggerSpringMvcPlugin customImplementation(){
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.includePatterns(DEFAULT_INCLUDE_PATTERNS);
}
}
You don't need your path provider any more.
You no longer need the property file

Using Testng in Eclipse Juno

I am using Eclipse Juno. I installed TestNG plugins properly. But when I want to run test I can't find a TestNG option in Run As. What's the matter?
My Class is
package com.oasisdigital.rental.client;
import static javax.ws.rs.core.Response.Status.CREATED;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import javax.ws.rs.core.Response;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.oasisdigital.rental.test.AbstractIT;
#Test
public class ClientResourceIT extends AbstractIT {
private ClientApi clientApi;
#Override
#BeforeMethod
public void setUp() {
super.setUp();
this.clientApi = new ClientApi(api);
}
#Test
public void shouldReturnEmptyListWhenNoProviders() {
assertThat(clientApi.getClients(), is(empty()));
}
#Test
public void shouldReturnClientAfterCreation() {
Response resp = clientApi.postClient("Jimmy");
assertThat(resp.getStatus(), is(CREATED.getStatusCode()));
ClientDto client = resp.readEntity(ClientDto.class);
assertThat(client.getId(), is(notNullValue()));
assertThat(client.getName(), is("Jimmy"));
assertThat(clientApi.getClients(), contains(client));
}
}