SonarQube demanding tests on conditions for Spring application with mock components - java

I have a Spring Boot service implementation that communicates with three different external services (APIs and SOAP Web Services). Some times those services can go into maintenance and I needed to implement a mechanism to “bypass” or “mock” them. The approach I am following to achieve this is to include some entries in the properties file:
service1.bypass.enable=true
service2.bypass.enable=true
service3.bypass.enable=true
So inside my code I just need to verify if those properties have value set in true and either use the right implementation or bypass (return a mock).
#Value("service1.bypass.enable")
private boolean service1Bypass;
//Inside the methods
if (!service1Bypass) {
callService();
} else {
callMock();
}
This is causing some troubles at the moment my code is scanned by SonarQube because I need to test when each service is mocked or not which I think is not relevant. Do you know if there’s any workaround or a better way to code this? this project is using Spring and Maven with Java 8

I believe there’s a misconception between “bypassing” and “mocking”.
When you bypass a service, it means you “skip” it, in other words you do not call that service and move forward with your next steps.
When you "mock" a service, your logic is not “skipping” the call to that service, you create a component (that belongs to your code project) that would imitate the behavior of the real service but it will return some “test” or “fake” response.
Mocking is pretty useful technique for testing or for the scenario you describe in which many of the services you are consuming can go into maintenance and impact other people that want to consume your service.
Now, going back to the problem you have, you can solve this in two ways, the first one, if you are using the Jacoco Coverage Plugin, then just add the following tags to your pom.xml file (since I believe you are using maven).
<properties>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPaths>target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.language>java</sonar.language>
<sonar.exclusions>YOUR PACKAGES GOES HERE</sonar.exclusions>
</properties>
Besides that, I believe your approach is not bad, but it can lead to some issues such:
You are mixing your “mocking” logic inside the business logic which can be a little bit messy.
When analyzing the code with tools such SonarQube (static analysis), you will find that each condition usually demands a test case (which I believe is the problem you have)
You are using now three properties because you connect to three services, but what if you need to consume eight or nine services? Would you add eight or nine properties? I mean, you can, but can be a little messy IMHO.
Since you are already using Spring, I believe that more than a workaround, a good approach to solve the issues would be to take a look to Spring Profiles.
For a more detailed tutorial you can also take a look to: https://www.baeldung.com/spring-profiles
Let’s take an example for your case:
You will only need to define one property instead one for each service in your properties file, this property is called: spring.profiles.active
You can assign one or more values to that property (separated by commas).
For instance:
If you want to mock one of the services, you can go with the following: spring.profiles.active=mockservice1
If you want to mock two (or more) services: spring.profiles.active=mockservice1,mockservice2
Instead of using conditional structures, you will create a class for each service you want to mock and annotate with #Profile(“mockservice1”) or handle through #Configuration or #Bean annotations.
Hope this can help you in some way to fix your issues.

Related

How to Decouple the existing services?

I need to come up new feature i.e. new maven module/services/domain objects. That module has dependency on other modules and call their services. I need to decouple that call from new services to existing services. Decouple here means modules does not know about each other either at compile or run time.
For example :- Instead of calling any other service directly ways can be
Put it on channel. Another service listens on it, process it once find object on channel and return the output on same channel where caller waits
for output
Channel can be any medium like object/queue/network etc
I am sure there should be many ways to decouple the call to existing services. There are two ways I can think of :-
Microservices :- As this is very small feature(will not require scaling in future) using the same Database. So, I am not convinced here
ESB :- Not sure just to decouple the existing service calls , ESB is the good way ?
Does spring provides any way to decouple the services ? Looks like Sprint events comes closure where events are published and listener get notified.
But spring listener does not return the output . Anything else in spring can help here ?
Are you asking about removing the classpath dependency, or if you should choose ESB, micro-services. The latter sounds like something which is more of a discussion you should have in your business than a SO question.
If you simply want to remove maven dependency hell maven creates, what you could do is create a project which has interfaces defining your old services. Your new services would work with these interfaces as opposed to depending on your old services directly. Of course however you will have to have some overarching project which as everything in it's classpath or you need to use OSI container or something of the likes. But you will be able to keep developing your new services as you wish without them knowing about your old services.
In regards to the type of architecture you want to use that is highly debatable and opinionated with no clear cut answer. But I will say that I don't think avoiding large classpaths is a great reason for implementing microservices or ESBs, but that's just my opinion. If that is your only real reason you want to go down that path I suggest don't.

Mocking / stubbing "third party" services during integrated development

The application I am currently working with is being worked on by 3 separate teams, each working away on different functional areas that come together at the end of the day. The difficulty is keeping the 3 teams always in sync and not having one team's issues affect another. I am looking for a way that I can stub out / mock the calls that are being made to some of these services provided by the other teams so that we can work separately most of the time, yet quickly switch back to integrated mode when needed.
Ideally I would like:
- during normal development, I could turn on a flag and those services will be mock services (for example, when I am just developing away on my part of the code and don't really care if the other team's service returns the right thing, just that it returns something)
- I don't want to have add code to check this flag everywhere in the code and if it is on, use the mock, else use the real thing... I just want it to automatically know to use the mock class when this flag is on
We are using Java 7 + CDI + Jboss. Is this possible to do with some kind of wiring or filters?
TIA.
Using Alternatives you can achieve this better ways, you can switch back to integrated mode when needed with disable alternative in beans.xml
CDI Alternatives are so good for the Mock service.
Instead of having to change the source code of your application, however, you can make the choice at deployment time by using alternatives.
Alternatives are commonly used for purposes like the following:
To handle client-specific business logic that is determined at runtime
To specify beans that are valid for a particular deployment scenario
(for example, when country-specific sales tax laws require
country-specific sales tax business logic)
To create dummy (mock) versions of beans to be used for testing
Alternatives allow you to overwrite this at execution time using the beans.xml file - a simple deployment artifact.
A typical scenario would be to use different beans.xml for different environments and thereby enable mock-alternatives for components that you don't want to execute on your local / integration environments.
Using Alternatives in CDI Applications
In Spring-based applications (using dependency injection), I've accomplished this by keeping two application contexts, one configured to use stubs and one configured to use real code. I wrote some wrapper code to load the appropriate application context at the right time, but you could manage it other ways, i.e. with separate run targets that use a different classpath.
In terms of the stubs, I've often created them by hand (i.e. written stubbed services that wrap a spreadsheet of canned data or generate random data), but Mockito could be useful when building certain kinds of stubs.
Depending on what kinds of resources you need to stub (and whether you have a budget), another option is service virtualization. I don't have any direct experience using service virtualization tools, but my current client is using the commercial LISA tool to stub out a SOA service layer. I gather that several companies sell similar tools.

Unit testing a service, which works as a mediator between two other services

I have a service, which works as a mediator between two other services. It basically validates the inputs, then passes them to those two service sequentially (by trying to keep transactional integrity), and then, if everything goes well, saves a result to the database.
My problem now is to test this service in isolation. Of course, I can provide stubs to satisfy the dependencies. I can also test the validation of inputs, whether appropriate data is saved in the DB in a normal case, as well as whether transactional integrity is kept if any of the dependencies throws an exception.
Yet, this is only half of what the service really does. My dilemma is if I should try to prove whether the other two dependency services actually processed the data appropriately as well? The scope of my service is quite broad, so I guess it is better to also know if the dependency services also did their job well. Yet, this gets out of the scope unit testing, and moves into integration testing, right?
I am kind of confused here.
If you're asking about unit-testing, then the way to do it is to test the class in isolation using mocks or stubs.
BUT, if you feel that just doing that is not enough, you can write some component tests, where you use the all the real classes you want to test, and use a stub (or inmemory) database and mock some of the dependencies that you consider not important for what you are trying to test.
In the past, I've tested small clusters of classes that had a high interaction between them in this way (and sometimes skipping unit-tests for those classes, as the component tests covered all the scenarios). Obviously, the problem with doing this is that the number of scenarios grows almost exponentially the more classes you're testing. Maybe you can test the bridge and the 2 real classes that use that bridge.
You should do both.
For unit testing, definitely use mock-objects for dependencies, preferrably using a tool like EasyMock. As a sidenote, if you feel that the functionality of your mediator service is too broad for unit testing, you may want to consider breaking it down into smaller pieces.
Of course, you additionally should do integration testing as well, using real dependencies, to make sure your services work together as intended.

User-dependent bean definition in Spring

I'm creating a Spring-based Webapplication where I use Spring to add the implementation of a service to the defined interface. So far, so standard. Works fine.
I want to allow a user to overwrite applications behavior at runtime for his session. For that I want spring to change the implementation behind an interface depending on the user-session.
A use case for that are automatic testcases that run on INT and should test the output of an email created by the system. On INT there is an email-serivce configured sending emails to our mail-server. I dont want the testcase to have to check mails using a mail-Protocol. I want in case automatic testcases are running to chenge the email-implementation to write the email as comments to the HTML, so my tests can easily check the result. And so there are some more such cases where it would be nice to change the implementing bean for special circumstances.
Is there a concept in spring that helps me to implement such a feature or do I have to create that on my own?
Additional information: It's all about automated acceptance tests. That tests run on systems that we share with maunual testers.
=> Manual testers want to get a real email for their tests
=> Automatic tests reduce complexity by not receiving emails, just checking the email-content with less dependencies.
There was no problem, if we had two systems, one configured for humans needs and one for automated tests needs. But thats not the case, so I need a way to change the systems behavior on runtime.
It is usually done in the following way:
set up tests using spring-test module which lets you create a spring context for testing and inject beans into your test classes,
use the same context files for tests as you do for production except create a separate spring profile where default mail service implementation is substituted with a mock,
write a test case where you simulate steps done by user programatically and finally you assert something like assertEquals("<expected_email_text>", mailServiceMock.getLastEmail()).
From your question it is not clear why you would deviate from the standard approach described above. If you explained your reasons perhaps it would be easier to come up with an appropriate answer.

Where should i put classes only used for development?

I started using dependency injection with roboguice and created an interface like DataProvider. I have an implementation which retrieves the data from some WebServer located in the WebServerDataProvider class. In Order to eliminate the waiting for the webserver i added a DummyDataProvider.
Where would i put such class? I don't like that it is in /src/main/java/my/package/providers/ since it is not real part of the application, but still i need it for development.
Typically you would use such a class in your unit tests. Roboguice works well with Robolectric , which allows you to mock things like http access. If you do that you would put your code in src/test/java/...
You could put it into the main project if you want to use it for fiddling around with the application without bothering the server each time and deactivate it with some constant for deployment, e.g.
if (DEBUG) {
setDataProvider(new MockDataProvider());
}
Proguard should be smart enough to remove this unused class if you remember to reset your variable (you might have to fiddle around with the settings there).

Categories