CXF (SOAP) Web Services integration test - java

Just implemented the SOAP Web Service using CXF. It is easy for me to write some unit tests using the mock framework. But not quite sure what's the best way to write some integration test for my web services. The implementation is something like this:
#Autowired
private InvoiceService invoiceService;
#Webservice(endpointinterface="xxx")
public Invoice retrieveInvoiceById(String id) {
Invoice invoice = invoiceService.getInvoiceById(id);
return invoice;
}
The InvoiceService will invoke the method to retrieve the invoice from a text file or some file system and then return. So how should I write the integration test to test the whole?
Thanks guys.

Write your unit tests so that the actual test will start Jetty server and expose your web service as real endpoint during test run. If you are using any database, use Derby or some other database which supports in-memory feature.
For e.g. just declare your endpoint in your test context spring file:
<jaxws:endpoint id="someProxy"
implementor="#yourWebServiceImplBean"
wsdlLocation="src/main/webapp/WEB-INF/wsdl/InvoiceService.wsdl"
address="http://0.0.0.0:12345/YourService/services/InvoiceService"/>
This is enough to start Jetty instance and expose your web service. This will start Jetty instance on port: 12345. Autowire this bean into your test class and you are ready to call methods.
Also you need to include this dependency in order Jetty to be run in unit tests.
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
<scope>test</scope>
</dependency>

Related

How to set up Camunda for unit testing in Spring Boot

I am able to run a Spring Boot application with Camunda for workflow management. My pom.xml with Camunda related dependencies are shown below.
<dependencyManagement>
...
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-bom</artifactId>
<version>7.15.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
<version>7.15.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
<version>7.15.0</version>
</dependency>
<!-- dashboard -->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine-plugin-spin</artifactId>
</dependency>
<dependency>
<groupId>org.camunda.spin</groupId>
<artifactId>camunda-spin-dataformat-all</artifactId>
</dependency>
I have just one .BPMN file. My application.yml file looks like this:
spring.main.banner-mode: console
server.port: 9090
springdoc:
model-and-view-allowed: true
swagger-ui:
operationsSorter: alpha
spring.jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
format_sql: true
spring.datasource:
initialization-mode: always
platform: postgres
url: jdbc:postgresql://xxxx
username: xxxx
password: xxxx
spring.flyway.enabled: false
camunda.bpm:
admin-user:
id: demo
password: demo
generic-properties:
properties:
generalResourceWhitelistPattern: "[a-zA-Z0-9,'_\\$\\-\\.\\+\\!\\*\\(\\)]+|camunda-admin"
In the codes, all I have to do are just to declare the Camunda objects and I can used them without further setups:
#AutoWired
protected final RuntimeService runtimeService;
#AutoWired
protected final TaskService taskService;
#AutoWired
protected final IdentityService identityService;
Now I am trying to write unit tests. It seems that there are more than one way to set up Camunda for unit testing, but I am not able to get any of the examples I found working. By some trial and error, I managed to get the following codes to set up Camunda for unit test.
#ActiveProfiles("test")
public class EntitlementServiceTest {
private RuntimeService runtimeService;
private TaskService taskService;
private IdentityService identityService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
.setJdbcUrl("jdbc:h2:mem:database_user;DB_CLOSE_ON_EXIT=FALSE")
.setJobExecutorActivate(true)
.buildProcessEngine();
runtimeService = processEngine.getRuntimeService();
taskService = processEngine.getTaskService();
identityService = processEngine.getIdentityService();
}
...
}
But I am not sure if this is the correct way to do so, so it would be better if someone points this out. The codes don't seem to have loaded anything from the application file for unit testing, application-test.yml. Replacing the hardcoded JDBC URL with ${spring.datasource.url} does not work at all. And even though I have set the camunda.bpm.generic-properties.properties.generalResourceWhitelistPattern, application-test.yml, it is obvious that it is not being read.
You have basically two ways to test a camunda spring boot application:
1st: run a camunda engine in memory, without spring. This can be very useful to test process flows, delegate behavior and so on. In that case, you will use the "ProcessEngineRule" from the core (junit4 style) or the junit5 extension (camunda-bpm-junit5). You will probably mock a lot of services and repos because you focus on the camunda flow. You do not need to annotate with "ActiveProfiles", as you are not running a spring context.
2nd: Run your tests using the SpringRunner or the SprinExtension and let spring handle the engine setup. This is just a plain spring boot test which will run everything you specify via yml and profiles and you will be able to inject all the camunda services.
Neither of these approaches is "better", they focus on different things. According to the testing pyramid, you would have many "real" unit tests, that do not even run camunda in memory just to verify your code works, some rule-based flow tests and a few integration tests using spring boot tests.
The camunda best practices guide will help configuring the scenarios: https://camunda.com/best-practices/testing-process-definitions/
Sidenote: When you mix plain-unit and spring integration tests, you should switch to constructor based injection to make it easier to manually create instances of your services without using reflection.

How to implement a recovery mechanism when a microservice is temporarily unavailable in Spring Boot?

I'm learning about microservices communication, and I developed a financial transactions app with these technologies: Spring Boot, Spring MVC, Spring Data JPA and Hibernate Validator.
There are 2 microservices, the first microservice is for validation, it is a REST API with POST methods. And the second microservice is for persistence. And the communication between the 2 microservice is asynchronous and I'm using JMS and ActiveMQ for it.
After that I need to develop a recovery mechanism for the case when one of the microservices is temporarily unavailable. Can someone tell me how can I do this recovery mechanism? Thank you in advance!
You can use Hystrix framework for using circuit breaker. Its simply wrapping your class with proxy , if your method considered "not working" based on your configuration its re-direct your call to fallback method.
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
MainApp
#EnableCircuitBreaker
public class AppName {}
Class that run your business method
#Service
public class ClassName {
...
#HystrixCommand(fallbackMethod="fallbackMethodName")
<method signature> {
}
…
<method signature> fallbackMethodName(...) {
...
}
}

Integration tests of Spring application

I am trying to implement integration tests for my Tomcat application, but my issue is that the application is launched separately from the tests so the tests cannot access the application context and neither the database.
My idea is running the tests "within" the running application, so I can #Autowire EntityManager and check for instance the state of the database during testing or even create database entities for testing.
My only idea of doing this is to actually run the application programmatically from the tests as ClassPathXmlApplicationContext("applicationContext.xml") and the access the Context. This would work, but it would be very hard for debugging as we wouldn't be able to use Hotswapping during the testing. Also I guess the server would be stopped as soon as the tests would end. I guess that is not the best and correct solution.
EDIT:
My question was probably unclear, so I will try to clarify.
I have a Tomcat application with Spring and Hibernate. The Spring beans and Hibernate database connection is initialised when the Tomcat application is started. The issue is how to run the tests of the active Spring beans from methods annotated with #Test in src/test/java which are started separately.
Consider this class:
#Component
class MyRepository {
#Autowired
EntityManager em;
#Transactional
public void myMethod(MyEntity entity) {
// do some job with entity
...
em.flush();
}
}
This class will be initialised with Tomcat as a MyRepository bean.
To test it, I cannot just call new MyRepository().myMethod(...) - I need to access the bean. The issue is accessing the bean from the #Test method:
#Test
void testMyRepository() {
Item item = ...
// then use the repository to handle the entity
context.getBean(MyRepository.class).myMethod(item);
// then assert the state of the database
context.getBean(EntityManager.class).find(Item.class, ...) ...
}
I can probably get the context in the initialisation of the tests with
ApplicationContext context = ClassPathXmlApplicationContext("applicationContext.xml");
But it would mean launching the whole application each time the tests are started. The better solution would be if the application could run separately from the tests.
Hope my problem is more clear now.
I would suggest you to use the SpringRunner to start the Spring application context and perform your tests on that running instance. You can customize the context the way it doesn't contain parts you don't want to tests and you can create mocks for components that require some external resources (REST clients and such). Take a look at the Spring docs or Spring Boot docs.
If multiple tests use the same Spring context configuration, the context is started just once and reused. So it's good to have it's configuration in a parent class of your tests. You can autowire any Spring bean into your test and test it.
You can use an in-memory database (such as H2) instead of a production one, so your tests are not dependent on an external infrastructure. To initialize the database, use tools like Flyway or Liquibase. To clear the database before each test, you can use the #Sql annotation.
You can find many examples of projects with such tests, for example my own demo.
If you want to test an external system, I would suggest something like JMeter.
Unfortunately you cant mirror your classes and use them in your tests. Thats a big disadvantage of web services. They always depend on user / machine interaction. With a lot of effort you can extract the functionality of the essential classes or methods and construct test scenarios etc. with jUnit.
The Overview of your possibilities:
special drivers and placeholders
you can use a logger with detailed log-level and file output. Then you created scenarios with the expected result and compare it with your log files.
Capture replay tools. They record your exection and replay them for monitoring.
I can also recommend using Selenium for the frontend tests.
Hope it helped.

How to write junit test cases for Jersey rest with spring dependency injection

I have web application which uses technologies like spring , hibernate and Jersey Jax-rs rest for web sevices.
I can write the junit test cases for Dao layer as well as Service layer but i am not able to write junit test cases for jersey Rest which internally injects spring components.
Can anyone help ?
thanks.
You can use RestAssured for rest unit tests
You can find detail explanation in there
http://rest-assured.io
Sample Rest Unit Test from my own trial
#Test
public void createEntityShouldReturnCreated() throws Exception {
given().port(DemoApplicationTests.serverPort).contentType("application/json").body(detailDto).when()
.post("/api/employee").then().statusCode(201)
.header("X-demoApp-alert", "demoApp.entity.created");
}

Don't understand how Spring (Boot) Data REST is told to create API endpoints

I have currently have an application that is using Spring Boot and Spring Data. I have my domain objects that were reverse engineered from my database and I have several repositories (classes). Each repository is an interface that extends the CrudRepository.
import org.springframework.data.repository.CrudRepository
interface MyDomainClassRepository extends CrudRepository<MyDomainClass, Integer> {
private MyDomainClass findByName(String name);
}
At this point I would create a service that would implement these items. The service would then be called by a REST controller.
I wanted to be able to have Spring create my REST API automatically if possible and I found the Spring Data REST project. I found this http://spring.io/guides/gs/accessing-data-rest/ and I can follow that guide, but I don't understand what is enabling the "REST APIs" to be created "automatically". I could understand it if the #RepositoryRestResource annotation caused the API to be created but in that guide it explicitly says
RepositoryRestResource is not required for a repository to be exported. It is only used to change the export details, such as using /people instead of the default value of /persons.
Does including in my POM file and rebuilding "automatically" allow Spring Data to create the REST endpoints?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
What keyword, section am I missing that makes it so the API endpoint is created automatically?
Spring Boot is opinionated. It has opinions like using tomcat as your application server or logback as your logging utility. When you pull in
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
It has opinions that when it detects (by classpath scanning) interfaces/classes that extend/implement Repository it will assume that those classes should be served as RESTful resources. RestRepository allows you to customize this behavior by changing the endpoint or not serving the resource at all (exported = false).
Spring-Data-REST does automatically setup the resource to handle GET/POST/PUT/DELETE requests. Are you familiar with REST/HTTP? Those would not be discrete endpoints, GET/PUT/POST/DELETE are http verbs, so there wouldn't be a resource/1/delete endpoint.
Spring Data Rest implements six controllers, in the package org.springframework.data.rest.webmvc:
RepositoryController: handles /
RepositoryEntityController: handles /{repository}
RepositoryPropertyReferenceController: handles /{repository}/{id}/{property} and /{repository}/{id}/{property}/{propertyId}
RepositorySearchController: handles /{repository}/search and /{repository}/search/{repoFunctionName}
ProfileController: handles /profile
RepositorySchemaController: handles /profile/{repository}
They are essentially the same as Spring MVC Controllers, except they are designed to work with Spring Data repositories in a general way
So, if you do GET /foo where foo is the path of your fooRepository, then Spring Data Rest will call RepositoryEntityController.getCollectionResource(), and invoke fooRepository.findAll(...), wrap the result in some HATEOAS objects, then marshal to JSON, using Jackson

Categories