Load testing for java client/server application - java

I have written a java client server application (not http), which i need to load test. However, most tools out there such as jmeter and grinder seem to be targeted to http requests. Any suggestions?
Thanks!

JMeter allows writing pluginns. If your application uses protocol other than HTTP it seems that the protocol is proprietary, so writing tests requires some custom implementation anyway. JMeter allows this and it is highly recommended.

since we have no idea what protocol you're using, write your own client in a way easily extendable for load testing.

You could have a look at Soatest which claims to be socket based and should be able to use whichever web protocol you are using (hopefully TCP/UDP).

You can use the JUnit4 or JUnit5 based load runners below which can simply accept your Unit tests and generate load on the target server. These need not be HTTP tests, these could be any tests annotated with #Test
JUnit4 based load runner
JUnit5 based load runner
The load configs look like below to ramp up or ramp down your load:
number.of.threads=2
ramp.up.period.in.seconds=10
loop.count=1
Your load test will look like below:
#LoadWith("our_load_config.properties")
#TestMapping(testClass = AnyTestEndPoint.class, testMethod = "anyTestMethod")
#RunWith(ZeroCodeLoadRunner.class)
public class LoadTest {
}
Your JUnit test which is fed to the load generator,
The test class looks like below:
import org.junit.Test;
public class AnyTestEndPoint {
#Test
public void anyTestMethod() throws Exception {
...
// You can have your client code invoking the target server
...
}
}
Note:
You can feed multiple Junit tests too to the load reactor, to generate load on different part of the server logic/apis/processes.
Visit the HelloWorld Examples for more details.

Related

Using LambdaClient.invoke in QuarkusTest how do I provide custom headers?

I'm trying to integrate Datadog into a Quarkus lambda function. The unit test is failing with a NullPointerException because Datadog can't get the function ARN from the context. It looks like there is a need to supply this header Lambda-Runtime-Invoked-Function-Arn in the HTTP request.
Is there anyway to customize the request headers using QuarkusTest? We are using LambdaClient.invoke.
Generally tests should be as close to the production run as possible, so altering headers does not seem to be the right path.
Is the unit test focused on the datadog part of the code?
If not:
If datadog just broke the existing unit tests, you have multiple options to fix it:
With #QuarkusTest you could just Mock the datadog related parts and register that instead of the original using #InjectMock.
I also found that using #QuarkusTest for unit testing can be a bit tricky in some cases and using plain Junit5 with Mockito can be a bit simpler with less unpredictable 'magic'.
If yes:
Since most things involving datadog is about sending data to an external service this might be more suitable for the scope of an integration test instead of a unit test. In that case you would need a test environment, or maybe reconsider if you really need to test external data collection at all.

Using Mockito for API Stubbing Load Test

I have a Spring Boot application with a REST API. Behind the scenes it uses a vended SDK to call the vendors service. I need to run load tests on my application, but don’t want to call the vendor API and accidentally crash their system during testing.
Is it possible to use Mockito outside of a JUnit test to create a mock for the vendor SDK objects during the normal application runtime?
I figured I would use a profile based configuration beam to enable the mocked object when profile is “performance-test”. But I can find no article/discussion/mention of anyone using Mockito this way and it is making me second guess my approach. Thoughts?
You probably should look for using wiremock or similar software to mock the vendor service, like here: Integration Testing with a fake server
Wiremock is a stub server that you can conveniently start/stop from within JUnit tests. It acts like the remote server when you set up responses. The documentation is really good, I do not want to copy&paste all of it here.
Just a sample:
public class MyTest {
#Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());
#Test
public void exampleTest() {
stubFor(get(urlEqualTo("/my/resource"))
.willReturn(aResponse()
.withStatus(200)
.withBody("<response>Some content</response>")));
...
verify(postRequestedFor(urlMatching("/my/resource/[a-z0-9]+"))
.withRequestBody(matching(".*<message>1234</message>.*")));
}
}
For loadtest, you would rather run the stub standalone somewhere, and have some script set up the responses.
You probably don't find mention of Mockito because embedding mocks with stub responses into your application is a bad idea and will not help you getting realistic results for load tests (because your responses will be much faster and not pass through serialization/deserialization).
Else also look here:
How to mock remote REST API in unit test with Spring?

Integration tests fails if run via maven, but passes if run via IDE

I have an acceptance test module that does an ejb call to another module. But for this acceptance test, I don't want it call the ejb directly as this may cause my tests to be very slow. So to over come that, I used SimpleNamingContextBuilder to mock the JNDI call. For my acceptance test, I am using Cucumberframework.
I created my own annotation #mockJNDIServices, the java method that does the JNDI looks like
#Before("#MockJndiEntityService")
public void mockJndiService() throws NamingException {
final EjbServiceRemote ejbService = new EjbServiceRemoteStubImpl();
final SimpleNamingContextBuilder contextBuilder = new SimpleNamingContextBuilder();
contextBuilder.bind(EjbServiceRemote.EJB_NAME, ejbService);
contextBuilder.activate();
}
EjbServiceRemoteStubImpl is a stub I would like tests to call instead of the service itself.
and the feature file has the heading
#MockJndiEntityService
#transaction
Feature: Lookups from library of policy
When I run this code via the IDE (Intellij), it works fine and everything passes.
But when I run it through the build tool (Maven), I get the remote lookup failure
Caused by: javax.naming.NameNotFoundException: Name
[ejb/EjbServiceEJB#ejb.service.EjbServiceRemote]
not bound; 1 bindings:
[ejb/EjbServiceEJB#ejb.service.EjbServiceRemote
It seems like the annotation is not being applied for each feature/scenarios.
Has anyone ever came across this? your help will be much appreciated.

Sling Remote Junit Test Case

I'm trying to execute a JUnit test remotely on an Adobe AEM instance, using the JUnit Servlet. Post for reference: Which Testing framework will suit for Adobe CQ5 Project?
I've defined my testcase and was expecting to be able to see it at this URL
http://localhost:4502/system/sling/junit/
It does not show up though.
The test runs correctly with mvn test.
it's a very simple test case (junit3):
import junit.framework.TestCase;
public class mySampleTest extends TestCase {
public void testSomething(){
return;
}
}
What do I need to do in order for the testcase to be available in the Sling remote JUnit test servlet?
I think you need to add annotation #RunWith(SlingRemoteTestRunner.class). Also you should read about it here and you can see example here

Integration Testing with Redis

I've started using Redis in my project with the help of the Jedis library. All is working fine but now I have a problem that my functional tests requires Redis to be up which I want to avoid in my Continuous Integration. What is the best way to do this?
I've implemented a simple redis embedded runner for Java:
https://github.com/kstyrc/embedded-redis
Currently, it uses redis 2.6.14 for*nix and https://github.com/MSOpenTech/redis for Windows. However you can utilize RedisServer class to run your own run script.
I plan to extend the implementation to support RedisConf (bind, slaveof, port, dbfilename, etc). After this, I'll upload jar to clojars for mvn deps.
Here are few options you have for functional/integration testing:
Just start an instance of redis on you CI server. All tests will be responsible to do proper clean up after execution.
Try somehow to control redis process, i.e. have some shell script or job on CI server to start/stop it before/after running tests. At least some of the burden of setup/cleanup is removed from tests, as for each independent build you will have independent redis setup.
Control redis further by using some in-memory solution like the one you mention for cassandra(if it exists).
One thing to mention is that integration tests should not replace unit tests. Unit tests should probably be preferred and they can cover more cases whereas integration tests can be used just to check that all parts of application play nicely together. And i think this is the reason why a lot of people choose to go for option number one.
Here is a similar question about mongodb The answer has a link to the project which works for second option(controls mongodb process) If you follow some related links on the project page there's also something called nosql-unit. This one i think tries to cover option three. I didn't use it but looks like it has something for redis too.
You can start Redis server on an arbitrary port via the command line: redis-server --port 7777. So for the purposes of integration testing, you could start on Redis on an available (or random) port, making sure that Jedis is configured to use that port.
In this way, you've got a "fresh" instance of Redis that you know won't conflict with any other processes, including other test runs occurring at the same time. This is as close as I can think of to the analogue of running an in-memory/embedded database for integration testing.
For pre-loading Redis with "canned data," use the --dbfilename <file> switch: redis-server --port 7777 --dbfilename test.rdb.
try nosql-unit. It supports redis unit test with java.
I have tried EmbeddedRedis and found that many Jedis interfaces are not supported. Hence using EmbbededRedis is not a good idea, especially when you are using some advanced redis function like "pipeline".
I suggest using ManagedRedis for unit test:
download a redis source code from redis.io into your test resource
build a redis-server in the $(your-redis-dir)/src
write a unit test with ManagedRedis, here is an example. Note that "REDIS_HOME" is the dir where your redis code downloaded, ManagedRedis will find redis-server in ${REDIS_HOME}/src
run you unit test.
As #ksytrc mentioned in his answer I basically used his solution. It was working in this project.You just need to add embedded-redis dependency.
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.6</version>
<scope>test</scope>
</dependency>
then in test class define the redisServer
RedisServer redisServer;
#Before
public void setUp() throws IOException {
redisServer = new RedisServer();
redisServer.start();
}
Also define application.yml with below credentials.
spring:
redis:
host: localhost
port: 6379
The better way that I could handle this same problem was create a Spring service that handle the RedisTemplate. After that, I just use #MockBean to mock the service and abstract the lack of a Redis instance running during my tests.
Per example:
#Service
class RedisService {
#Autowired
private RedisTemplate<String, SomeClass> redisTemplate;
SomeClass get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
And in the integration test:
class IntegrationTest {
#MockBean
private RedisService redisService;
#Before
public void setup() {
SomeClass someClass= new SomeClass();
when(redisService.get(anyString())).thenReturn(someClass);
}
}
I'm skeptical to use some redis memory database solution, because I understand that the actual alternatives is not "officially" recommended by the Spring team.

Categories