I have a stand-alone java app that creates services using Java JAX-WS. I would like to create test cases to test the services, how can I go about that?
I thought about using an external client, outside the project, is this the best method?
Strictly speaking, deploying a web service and testing it is an integration test, not a unit test. With that said, it's probably better to unit test this. I would make a separate layer that implements the business logic, and other layer that exposes it as a web service. Then you can test the business logic, without having to worry about the web service.
After all, you probably don't want to bother re-testing the web framework you are using to start up a web service. You really want to test your business logic. This will let you create faster and less brittle tests.
The arguments about integration vs unit tests could go on and on. Just removing the web service layer and testing the inner business logic does not change an integration test into a unit test.
IMHO web services are a public API into your application, and you need them to work consistently between versions of your app. Therefore I would recommend an extensive soapUI test suite, hitting your app and db as if it were a regular client. You can add assertions to check for expected success and failure messages (don't forget to test what your web services do when incorrect data is thrown at them). Also you can add groovy asserts to check your database state after each web service call.
I would fully recommend quick-running unit tests to complement the above, but getting a robust integration suite running every night against your overnight build will ensure the quality of your API and avoid many problems which would otherwise only be flushed out when your customers start hitting your services when your app has been deployed .
It is the nature of web services that they have no UI so are not well-tested if left to human testers.
I don't think I would test the actual web service endpoint or the client. I would move all of the business logic into some service layer and then unit-test those objects. For example:
#Path("/user")
public class UserWebService {
#Inject
private UserService userService;
#Path("/delete")
public void deleteUser(#RequestParam long id) {
userService.deleteUser(id);
}
}
Then I would unit test my UserService implementation.
Related
I have a rest controller for creating and getting employees. To test these endpoints I have two classes. In one I mock the service layer and do status code checks such as:
Mockito.when(employeeService.createEmployee(any(Employee.class))).then(returnsFirstArg());
this.employeeClient.createEmployee(this.testEmployee)
.andExpect(status().isCreated());
In the other I start up a docker postgres database and don't mock anything. These tests involve multiple endpoints e.g. "If I create an employee and then get all the employees, the created employee should be returned".
Both these classes create an application context - the first uses the WebMvcTest annotation, the second uses SpringBootTest. For this reason I see them both as integration tests.
So then what do I call these tests? I'm currently using EmployeeControllerTest and EmployeeContorllerIT (running IT with the failsafe plugin), but the name for the first is a little misleading because it's not really a unit test.
I was thinking of using EmployeControllerMockedIT for the first, but not convinced that's the right way to go.
If you're mocking responses, I'd say its a unit test as you're testing the module of code in isolation from a network and 3rd party systems like a database.
If you're running a test against (real) 3rd party code/systems you don't control, its an integration (or functional) test.
Functional tests will invoke your service as if your system is a black-box where we don't know the internal details (vs. white-box where we know, and have access to change, the internals and invoke code as if we're making a method call rather than sending an HTTP request).
Functional tests may run against real/fake servers but there will typically be a running application waiting for requests. The point being here the responses are not "mocked", the request is made for real, from your code, to the third party code/system, and that system is expected to respond as the real server would.
We do not fake responding in functional tests but arbitrary responses may be provided from the real/fake server to simulate the data we expect to receive. It could be we write a fake HTTP service to "mock" a real API. It will provide the exact same type of responses over the network, and be invoked over the network. Or we could just spin up a dockerised database and send queries to it and receive responses from it. The database will be a real database-server, rather than a mocked response we pre-specified in code.
Functional tests (of a web service) will begin from outside your application and ensure requests are answered over the network layer. i.e. you'll be making an HTTP request to invoke the service.
Integration tests of a web service will invoke the service at an application level (not over the network layer) so you may call a Controller class directly or invoke some code that is supposed to connect/integrate with a database from within the application. Integration tests will test your code is integrated correctly with third party code/a library/a database. Your tests should alert you to any situation where if the 3rd party code (code/system you do not control) changes in such a way that your software would break.
I have to work with some old java application.
There is a total of 6 projects which:
communicate using rest and mq and
already have some integration tests.
As part of this:
mvcMock mocks are used for the initial requests from test
additional http requests are made by services and
they go against dev server instead of calling code from current build;
it'll fail if my test use code which communicates with another project by new endpoint which dev do not have yet.
How I thought of testing this
My idea was to use single test project which will run all required projects using #SpringBootTest and mockmvc to mock real calls and transfer them inside test instead of using real endpoints.
The ask
I don't get how to make Spring to work with #Autowired and run 6
different WebApplicationContext's.
Or maybe i should forget my plan and use something different.
When it comes to #SpringBootTest its supposed to load everything that is required to load one single spring boot driven application.
So the "integration testing" referred in Spring Boot testing documentation is for one specific application.
Now, you're talking about 6 already existing applications. If these applications are all spring boot driven, then you can run #SpringBootTest for each one of them, and mock everything you don't need. MockMvc that you've mentioned BTW, doesn't start the whole application, but rather starts a "part" of application relevant for web request processing (for example it won't load your DAO layer), so its an entirely different thing, do not confuse between them :)
If you wan't to test the whole flow that involves all 6 services, you'll have to run a whole enviroment and run a full-fledged system test that will be executed on a remote JVM.
In this case you can containerize the applications and run them in test with TestContainers.
Obviously you'll also have to provide containers for databases if they have any, messaging systems, and so forth.
All-in-all I feel that the question is rather vague and lacks concrete details.
I have a service layer and a domain layer. I use plain native Spring repositories for the domain layer and in my test setup I'm mocking the db with dbunit.
#Repository
public interface ExampleRepository extends PagingAndSortingRepository<ExampleEntity, Long>, JpaSpecificationExecutor<ExampleEntity> {
}
Naturally I will assume that the Spring repository implementation has no errors and therefor the domain layer is no subject to tests.
My general knowledge about unit testing is that I would need to mock my domain layer when writing unit tests for my service layer.
With my assumption that the domain layer does not need to be tested, and the with the fact, that I use dbunit to mock my database, am I allowed to use this setup for unit tests of my service layer?
If I understood it correctly, in your tests the Spring context is boostraped, your service layers is tested along with your domain layer, and the data is inserted in your test database using DBUnit.
With that, let's start:
My general knowledge about unit testing is that I would need to mock my domain layer when writing unit tests for my service layer.
If you want to do a Unit Test, then this is correct. The way you describe your tests, it depends on both layers to be correct, and the DB must be running so, per definition they are integration tests.
With my assumption that the domain layer does not need to be tested, and the with the fact, that I use dbunit to mock my database, am I allowed to use this setup for unit tests of my service layer?
I wouldn't call the use of DBunit a database mock. It surely helps populating the database, but the DB is still needed to run the tests, and your domain layer will be executed (JPA, Hibernate or whatever ORM framework will be generating SQLs that will be executed against the DB). If you really want to mock the domain layer and the DB then you should consider using mocks (many mock libraries can help with that).
As for the final question, well if this setup is working for your project I suppose it's OK, but I just wouldn't call it Unit Testing, but Integration Testing. You'll have to accept that if your domain layer for some reason changes, it will probably break your service layers tests.
There are pros and cons on both approaches (unit vs integration). If it helps you grow your project with quality and good maintainability, then there is no "right" or "wrong" approach.
No, testing with dbUnit is integration testing.
Unit testing involves only the small unit of code under test with mocking of any additional interactions.
Integration testing involves a broader scope of the system with an external service, such as testing SQL with a database server and sending an email using email server. In both cases, we use "test doubles" instead of the real production ones to verify the system correctly interacted with the external service.
There are many test types, and the most common I see and implement are unit, integration, acceptance, and performance. All are valuable and have different pros/cons. It's best to have all types for a quality system.
I am just started to write JUnit test cases.Now I am writing a test method to test RESTful web service in java using the IntelliJ IDEA. My directory structure as this.
I am calling the web service from my test case as:
Response response = target.path("groups").path("registergroup").request().accept(MediaType.APPLICATION_JSON).post(Entity.json(stringEmp.toString()));
String output = response.readEntity(String.class);
I have added the multiple breakpoint in this test method and source classes.
Is it possible to jump Webservice classes from above request point?
If possible then how can I do that?
I am using the embedded jetty server to test which is also running from this module.
Testing REST services using JUnit only is in my opinion not worth the effort, because you usually have to mock a lot of the REST library internals in order to make it work, and it's very hard to test some of the service behavior anyway (e.g. what happens when the client specifies the wrong Content-Type or Accept headers).
Assuming you are using Jersey, you have two options :
use JerseyTest
use Arquillian
My personal preference goes to Arquillian because (among other things) the resulting tests are completely independent from what is being tested (i.e. you can change the implementation of the service and the REST library without changing the tests).
I am implementing an application that tests web services, and I am wondering if it is worthy to use spring testing.
In my application I call web services and test if the results returned match with the ones expected, so I don't need to inject any DAO.
Did I miss any other benefits ?
If you test an external webservice, you don't need spring. You even don't need java as you might as well write good tests with soapUI.
Anyhow, if you're testing your own webservice classes, you probably have to mock some services at testing time, and therefore spring testing might help alot.