Mocking AOP method implementation for unit tests - spring

I've a java application which has multiple modules - (GWT-)RPC services, perf-library, remote-client (All java code written/owned by my team). The perf-library contains Spring AOP aspects related code and it's primarily used to push intercepted method logs to a data store. Now, perf-library is dependent on another remote-client which actually maintains a queue and handles the job of pushing logs to the data store. So, in a way, perf-library just delegates the task to remote-client.
The business logic code calls intercepted methods which have AOP logic and hence there is a dependency on remote-client. Obviously, I don't want to connect to the remote-client from within unit tests. I think I need to mock the implementation of method push() which connects to remote-client. What I'm unable to figure out is how to use the mock implementation for the business logic code package unit tests.
To clarify things, I've modules like this -
RPC service module - e.g. method login() is intercepted.
perf-library - Has aspects (to intercept methods like login()) and implementation to call remote-client
remote-client - Push data to some data-store
Now, for writing the unit tests for RPC service methods, how do I get the mock implementation of push() as it is internal to perf-library. Let's say, I've an interface LogClient (having method push()) which is implemented by two classes (one for production and another for test). I can use this Test implementation for unit tests of perf-library itself, but how do I make the RPC unit tests use it. I'm new to Spring, so not sure if this can be done easily with Spring or anything else. Any help will be nice.
Note: We're using Spring for maintaining beans and DI.

Not sure exactly how but Mockito can be a good choice.
Check this link for details.

Related

What is correct way writing Integration test in Spring or Spring Boot based application

I am writing code for Spring Boot Rest application which interact with DB using Spring JPA.
My app have 3 main layers Controller,Service,Repository and it have CURD operations.
I want to follow TDD approach. My question is how do I populate data for each VERB implementation.
For example I am starting with CREATE impl and implemented CREATE flow with Controller,Service,Repo etc. Now to implement PUT,GET,DELETE I need to populate data while writing my tests. For this purpose I used Injecting Repository in my Integration test class and loaded data before my actual Test Runs or Used DataLoader with CommandLineRunner Implemention to pre-populate the data. Buy my collegue insisted me I should never use Repository in Integration Test class for populating data instead should User Service class bean and call CREATE implementation for required data population.
Is it any best practice or guideline documentation to design Integration Test and Unit Test?
And main question did we use Repository in Integration Test class for populating data or not?
The main motive of writing integration testing is to test the interface between two software units or modules. It focuses on determining the correctness of the interface. That means you should test your application in the sense of whether your app can be integrated into other software or not. In that case, your beans like repositories or services are not injectable or applicable from the other software except your endpoints that you are exposing through controllers.
Writing Integration Test
There are a couple of things you should consider before writing your integration test such as the scope of your test cases, scenarios of each endpoint, tools/libraries to write the tests, etc.
You can use something like RestTemplate or MockMvc to invoke HTTP requests(POST, PUT, CREATE, DELETE). For example, make a GET request with RestTemplate,
#Autowired
private RestTemplate restTemplate;
#Test
void givenYourObjectTypes_whenGetYourObjectTypes_thenStatus200()
ResponseEntity<YourObjectType> response = restTemplate.getForEntity(requestUrl, YourObjectType.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
My question is how do I populate data for each VERB implementation.
There are annotations called BeforeEach and BeforeAll, you can use either of them in a setup method to populate your data
Is it any best practice or guideline documentation to design Integration Test and Unit Test?
There are a lot of documentations you can find out in google. But once you grasp the core concept of the test, you will be intimated to workaround. Still, I would refer to you to have a look at an article by Martin Fowler on Integration Test (It's my personal preference).
And the main question did we use Repository in Integration Test class for populating data or not?
Populating data using repositories is not the recommended approach. Instead, I suggest you use CREATE API to populate data which would be a real scenario while integrating with other services/UI/modules/software.
Moreover, You could try H2 dependency with scope test while testing your application which makes it faster to perform the test cases. But note that it is only applicable if you are using SQL database.

Unit testing for Spring Boot API

I'm developing a Spring Boot Web API, and I'm currently writing the required units tests.
I was wondering : Isn't writing the units tests (JUnit + Mockito) for the controllers sufficient ? Since the controllers are the entrypoint of my application and that all the logic that is implemented within the Service side is called from the exposed API, why do I need to write test for the Service side ?
First of all, if you write your tests to cover "required level of tests" or requirement to "have some tests at all" having the production implementation already done, it is slightly too late. In the majority of cases having tests first, based on your requirements, contract, use case or anything it more optimal approach. Nevertheless, I don't know your situation and the thing you're trying to implement, so treat it as a suggestion and move on to the key thing you are asking about.
Your JUnit (preferably 5) and Mockito tests, which probably use MockMvc are very good unit(-like) tests to cover web communication concerns such as: HTTP request types, content type, encoding, input and output parameters JSON (de)serialization, error handling, etc. They are best to test with the service layer mocked. Thanks to that you can easily cover a lot of web cases without the need to prepare data in a database, etc.
The core logic has to also be tested. Depending what it is, it might be feasible to test it in the unit way (the easiest to write, can cover a lot of - also corner - cases). It could be supplemented with some set of integration tests to verify that it works fine also in integration (Spring Beans, DB, etc.).
If desired, you may also write some E2E test from the web call via (real) HTTP requests through controllers, services to a database/datastore (if any), but I would limit it only to the most important scenarios to use it in your CI/CD pipeline to verify that a deployment finished successfully.
Disclaimer. I've found this approach useful in multiple situations, but definitely in some other circumstances it might be good to change the balance point to better apply testing.
I think you are probably getting confused between unit and Integration tests.
If you are using Mockito you are probably referring to unit tests wherein, the scope of the Test Class should be only the current class.
Any external method calls should be mocked.So in your case the service calls should be mocked in case you are writing unit test for your controller class.
Your Test Suite should contain
Junit for Controller-- To Test the interface contract points like HTTP Method, Request Parameters, Mandatory inputs, Valid Request Payloads.
Junit for all other classes including Service classes- This is to test your application classes core logic
Integration Test- Finally an integration test which can hit your controller endpoints with service classes and rest of the application code functionality.

Unit testing in spring mvc

If I want to unit test my dao classes in spring would I just call my service methods and test those or would you test the service methods separately to the actual dao methods?
Also should I mock the dao calls or actually use an in memory database like H2? I see that as more of an integration test although some tutorials do this, or would a standard approach be to test with mock database objects for the service tests and use H2 when testing the dao calls?
Finally.. My application has a rest API which is called from the web front end using the Spring rest template and so only the API web app accesses the database.
Would I test the rest methods in each web app using mocked objects and then Start a tomcat instance and integration test between the 2 apps? If I used tomcat and ran integration tests between the apps would connect up a database or mock objects in the API app?
Testing the rest calls from the web app relies really on how the API app's rest method responds so is this even worth testing in isolation?
I find unit testing quite confusing as some of it seems almost to be integration testing.
Does it matter if you run integration tests against H2 in memory but then in reality I would be using MySQL?
Trying to answer your questions in the order asked...
For unit testing DAO methods, you should test the actual DAO classes directly with a database in a known state. H2 is great for this, since you can run it without setting up MySQL for each test. Utilizing setup methods with the #Before annotation is great to make sure that the database will respond in expected ways.
For unit testing Service classes, you should mock the DAO classes, so that they will always behave in expected ways. If you use your service and DAO classes with actual data, you are now running integration tests, by testing multiple layers simultaneously. Both have their value, though is generally best to unit test before integration testing, to make sure each component is functioning.
The same goes for testing your controller, you should unit test it and mock the service classes, and then perform integration tests with mock requests to test request/response scenarios. Again, with this test setup you are now testing many layers and classes simultaneously. This is great, because it gives you a good idea of how your application will function in reality, but is not useful for isolating bugs.
H2 and MySQL obviously are not the same, and don't share all the same functionality, so you can't say with 100% confidence that an H2 test will pass in MySQL, but if you are just testing standard CRUD operations, it should do the trick.

JTA Callbacks in Spring

Is it possible to register some kind of callback with a JTA transaction in a Spring application?
I've got some mock services that are standing in for remote services that belong to another application that's normally accessed using Spring's HttpInvoker. These mock services model data in-memory in a trivial fashion using Maps and the like.
The Unit tests don't necessarily know which of these services might get used; the service the test case is targetting might use them behind the scenes.
The unit tests are transactional, and Spring's SpringJUnit4ClassRunner will rollback the transaction after each test, meaning that the state fo our unit test database is preserved between tests.
How can I rollback the state of this custom in-memory service implementation? If there was a way of finding out if there's a transaction currently going on, then I was hoping there'd be a way of registering a callback with the TransactionManager to be executed before the transaction is completed.
I don't think it's a good idea to clean up test mock in such an implicit way - tests usually perform cleanup explicitly.
However, if you really want, take a look at TransactionSynchronizationManager.registerSynchronization().

Test Driven Development For Complex Methods involving external dependency

I am implementing a Service Contract for WCF Service.
As per TDD I wrote a test case to just pass it using hardcoded values.
After that I started to put real logic into my Service implementation. The actual logic relies on 3-4 external service and database.
What should I do to my original test case that I wrote ?
If i Keep it same in order to make test pass it will have to call several other external services.
So I have question in general what should I do if I write a test case for a Business Facade first using TDD and later when I add real logic, if it involves external dependency.
Utilize a mocking framework (with dependency inversion or just a factory) so you can inject fake dependencies into the object. These can then then just return canned responses and/or be checked that the class utilizes the dependencies how you intended.
As an example, if your code calls a repository to save, we don't really care in the business method test that the repository did actually save to a persistance store, only that it got called and returned some data if required. What you're really testing is how your code reacts to what the dependency returned, or if it was utilzed correctly - but not the dependency's actual functionality
Ideally the first test should have been representative of how the class/method will work and return data, so the test would still be valid once you're finished.

Resources