jmeter: AbstractJavaSamplerClient - Do setUpTest only once for all threads - java

I am developing a Java Request Sampler with JMeter by extending AbstractJavaSamplerClient. The test goes like this:
public class JmeterTest extends AbstractJavaSamplerClient {
public void setupTest(JavaSamplerContext context) {
System.out.println("Test setup");
}
public SampleResult runTest(JavaSamplerContext context) {
SampleResult result = new SampleResult();
System.out.println("Test..");
result.setSuccessful(true);
result.setResponseData("Success");
}
public void teardownTest(JavaSamplerContext context) {
System.out.println("Test cleanup");
}
}
I created a jar out of this test class and pointed it through the JMeter UI (through Java Request Sampler). The problem in my case is when I run the test with 5 users, the setUpTest & tearDownTest methods gets called for every user as per design.
Is there any setting where the setUp and Cleanup methods get called only once for all threads in the thread group. My requirement is to do setup and cleanup only once for all threads.

Here are the options you can try out:
Perform setUp actions separately in setUp Thread Group
Perform setUp actions separately in the same Thread Group. Put setUp logic under the If Controller and use ${__BeanShell(vars.getIteration() == 1)} as condition
Modify your code like:
public void setupTest(JavaSamplerContext context) {
if (JMeterContextService.getContext().getVariables().getIteration() == 1) {
System.out.println("Test setup");
}
}
Both points 2 and 3 assume that setUp code will be executed only during first iteration of your test by each thread. Remember that JMeterVariables.getIteration() number is incremented only when Thread Group-level loops occur.

Related

How to test code that subscribes to an Uni?

I know that I can test a method that returns an Uni:
#Test
public void testUni() {
service.doSomething().invoke(data -> {
// run assertions
}).subscribe().withSubscriber(UniAssertSubscriber.create()).assertCompleted();
}
But what if I want to test the method that subscribes to the Uni itself? For example, consider this piece of code:
public void execute() {
service.reprocessAll().subscribe().with(
success -> log.info("Reprocessing ran successfully."),
error -> log.severe("Reprocessing failed: " + error.getMessage())
);
}
If I try to test it like this...
#Test
public void shouldLogSuccessAfterReprocessing() {
service.execute()
Mockito.verify(log, times(1)).success("Reprocessing ran successfully");
}
The test will fail due to a race condition. I mean, the test code will run before the actual code under test (the log.success call). So how can I tell the test to wait for the Uni to complete? Or how could I refactor this to make it testable?
The proper question would be how to design the code so that it is unit-testable which may lead a different answer than the one I will be writing here to respond to your current need.
Since the service#reprocessAll computation will be triggered on the background, and you have no means of controlling it behavior as your #service method simply returns void, you can block the calling unit runtime thread awaiting for the processing to finish:
#Test
public void shouldLogSuccessAfterReprocessing() throws Exception {
service.execute()
Thread.sleep(1000); // wait for reprocessAll to finish then proceed with assertions
Mockito.verify(log, times(1)).success("Reprocessing ran successfully");
}
For finer control, you can use the awaitiliy library for condition testing.

How to add multithreading to an application with jdbc

I'm new to multithreading and don't even understand what to do with a thread in my application. The application is a console game. The player chooses a hero, clan and actions. Gold is credited to the treasury for various actions. You can add from your pocket, complete a task or win a battle. Each action is a separate class. All operations are saved to the database. Here is the code that creates the operation object, it also saves changes to the clan treasury
public class OperationService {
OperationDAO operationDAO = new OperationDAO();
private static ClanService clanService = new ClanService();
public void createOperation(String reason, int sum) {
Hero currentHero = CurrentHero.getCurrentHero();
Clan currentClan = CurrentHero.getClan();
LocalDateTime currentDateTime = LocalDateTime.now();
Operation operation = new Operation();
operation.setClan(currentClan);
operation.setHero(currentHero);
operation.setReason(reason);
operation.setSum(sum);
operation.setAmountBefore(currentClan.getGold());
operation.setAmountAfter(currentClan.getGold() + sum);
operation.setDateTime(currentDateTime);
operationDAO.save(operation);
clanService.changeAmount(sum);
}
The problem is that it is implied that many players will simultaneously perform different actions and change the treasury of their clan. According to the task, it is necessary to enter multithreading, but the amount of the clan treasury before and after should be displayed correctly.
I also created a thread with the launch of the game, which pulls a large chain of method calls from different classes.
public class ThreadGame extends Thread {
HeroService heroService = new HeroService();
public ThreadGame() {
this.start();
}
#Override
public void run() {
heroService.startGame();
}
}
Question 1. Can methods from the chain also be considered threads? Or are they no longer part of it?
I also tried to create tests for my application, but some operations are not saved in the database and synchronized does not help.
public class Test extends Thread {
HeroDAO heroDAO = new HeroDAO();
OperationService operationService = new OperationService();
#Override
public void run() {
Hero hero1 = heroDAO.findById(4L);
operationService.createOperationForTest(hero1, "Победа в бою", 20);
operationService.createOperationForTest(hero1, "Победа в бою", 20);
}
}
public class App {
public static void main(String[] args) {
Test test = new Test();
Test test1 = new Test();
test.start();
test1.start();
}
}
I synchronized the createOperationForTest method, but the data is still stored incorrectly.
Question 2. Where to specify synchronized?
All the code you write in the run() function, will run in the thread that will be created when you execute thread.start();
For example:
In your class ThreadGame you have this function:
#Override
public void run() {
System.out.println("Hello, I'm a thread");
heroService.startGame();
}
When you execute the .start() function, a thread will be created and this thread will then execute the code in the run() function.
So in this case it will output "Hello, I'm a thread" and then execute your heroService.startGame() function.
All the code that you wrote in startGame() will be executed on this thread.
Note that you can create another thread, inside a thread.
Threads exist to provide asynchronous execution.
If you need to let a thread wait until another thread has completed something, you can use Semaphores! Here's a link to learn more about semaphores.
Elisaveta.
To learn about multi-threading I would recommend:
official Java tutorial on concurrency
Java Concurrency in Practice
But in short a thread lets us run something in parallel and use multiple cores of our CPU.
A good example of thread usage is a web-server.
The web-server receives HTTP-requests and for each requests it replies back with an HTTP-response.
In order to use all available CPU cores the web-server uses several threads (it's usually called "thread pool").
When a new HTTP-request arrives to the web-server the main thread delegate the task of the request processing to one of the vacant threads in the thread pool.
The thread is busy until it finishes the request processing and sends the HTTP-response, but after that it again becomes vacant and can be used to process new requests.
It's a frequent pattern in Java to have a thread pool to perform tasks in parallel.
In your case you can use threads to save new operations in parallel.
Something like this:
public class App {
final HeroDAO heroDAO = new HeroDAO();
final OperationService operationService = new OperationService();
final ExecutorService threadPool;
App() {
var numCores = Runtime.getRuntime().availableProcessors();
threadPool = Executors.newFixedThreadPool(numCores);
}
void saveNewOperation(long heroId, String reason, int sum) {
threadPool.submit(() -> {
var hero = heroDAO.findById(heroId);
operationService.createOperationForTest(hero, reason, sum);
});
}
void stop() throws InterruptedException {
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
threadPool.shutdownNow();
}
public static void main(String[] args) throws InterruptedException {
var app = new App();
try {
app.saveNewOperation(4L, "Победа в бою", 20);
app.saveNewOperation(5L, "Победа в бою", 30);
app.saveNewOperation(6L, "Победа в бою", 40);
app.saveNewOperation(7L, "Победа в бою", 50);
} finally {
app.stop();
}
}
}
With multiple threads you should be careful with static variables (it seems like CurrentHero in your code is a static variable that stores current hero).
When you process two operations in parallel there could be two current heroes.
In multi-threaded applications such information is usually passed explicitly to methods (sometimes multiple properties are grouped in a single context object which is usually a Map<String,Object> that stores an object-value for every property name).
synchronized is used when we want to guarantee that some block of code can only be executed by one thread at a same time.
Often we guard with synchronized a code that works with some shared resource (for example an established connection to the database might only be used by one thread at the same time).
Also synchronized allows us to guarantee that some group of actions happens atomically (i.e. the actions aren't interleaved with actions in parallel threads).
For your example synchronized might be required:
around clanService.changeAmount(sum): here we have a shared resource "treasury".
If the operation changeAmount consists internally of several actions, then you might want to execute them atomically.
around operationDAO.save(operation): here we have a shared resource "operation storage".
Again if save consists internally of multiple actions, then you might want to execute them atomically.
Additionally if operationDAO use internally connection to a database, then this connection might require to be used by one thread at a time
around
operationDAO.save(operation);
clanService.changeAmount(sum);
If you want these two operations to execute as a single atomic block.

Javafx - Concurrently reusing javafx Service<>

On JavaFx a reusable task is usually implemented on a javafx.concurrent.Service<>.
The question is: how to manage multiple UI interactions that triggers the Service multiple times?
Approach 1 - restart():
I could use service.restart(), but it cancels the running task and starts a new one. This is not the desired result, as I do not wish to cancel the first one.
Approach 2 - start():
To be able to use start() more than once, I would have to do this:
if(!isRunning()) {
reset();
start();
}
But if isRunning() is true, the second run is ignored.
I want to block the second run until the first one finishes, so no UI interaction is lost. So I wish to block or enqueue the tasks.
How would this be accomplished ?
If you want to stop users from trying to run the Service two or more times at once, simply disable all the UI nodes that launch the Service while it's running. One way of doing this is to bind the disable property of the Node to the running property of the Service.
If you want to queue up executions then it depends on what the Service requires. For instance, does it need any input? If not, just have some requests variable and increment/decrement it as needed.
public class Controller {
private int requests;
private Service<Object> service = new Service<>() {
#Override
protected Task<Object> createTask() {
// create and return Task...
}
#Override
protected void succeeded() {
if (requests > 0) {
requests--;
restart();
}
}
};
#FXML
private void startService() {
if (service.isRunning()) {
requests++;
} else {
service.start();
}
}
}
If the Service (or more specifically, the Task) does need input you'd still do something similar. Instead of using an int tracking the number of requests, however, you'd use a Queue (or some other similar object) that contains the needed information for each Task. When the Service completes and the Queue is not empty, restart the Service and grab the next element.

Unit testing a Threaded Application

I am having thoughts on how do I write a test case for this using mockito.
Example, part of my logic in my main thread is to create a thread that does 3 things.
Please see my annotated code below.
Now the RequestThread can be spawn many times depending on the number of inputs coming from the main program.
public class MainThreads {
public static void main(String[] args) {
RequestThread rt = new RequestThread("sample");
rt.start();
//RequestThread another = new RequestThread("sample-2");
//another.start();
//RequestThread newThread = new RequestThread("sample-3");
//newThread.start();
}
public static class RequestThread implements Runnable{
private final String request;
public RequestThread(String request) {
this.request = request;
}
#Override
public void run() {
//1. Instantiate a service passing the required request parameter
MyDataWebService service = new MyDataWebService(request);
//2. Get the returned data
List<String> dataList = service.requestData();
//3. Write to file
Path file = Paths.get("/someDir/" + request);
Files.write(file, dataList, Charset.forName("UTF-8"));
}
}
}
My issue is this, I could not figure out how to properly write a JUnit/Mockito test for a threaded class.
I am not that well verse on Mockito and JUnit in general so I am looking for a way to unit test
a threaded application.
Can somebody guide me on how can I unit test such thing?
You need to bring some changes to your code in order to make it more testing-friendly. In particular:
Objects that you want to mock should implement an interface
Do not instantiate objects to mock in the function that you want to test
Here is a rewrite of the classes so that you can mock MyDataWebService and test RequestThread. Based on this example you will more easily be able to write a full test for the MainThreads class.
public class MainThreads {
public static void main(String[] args) {
RequestThread rt = new RequestThread("sample");
rt.start();
//RequestThread another = new RequestThread("sample-2");
//another.start();
//RequestThread newThread = new RequestThread("sample-3");
//newThread.start();
}
public static class RequestThread extends Thread {
private final String request;
// One important thing to note here, "service" has to be non-final. Else mockito won't be able to inject the mock.
private MyDataWebServiceInterface service;
public RequestThread(String request) {
this.request = request;
//1. Instantiate a service passing the required request parameter
// => do it in constructor, or passed as parameter, but NOT in the function to test
service = new MyDataWebService(request);
}
#Override
public void run() {
//2. Get the returned data
List<String> dataList = service.requestData();
//3. Write to file
Path file = Paths.get("someDir/" + request);
try {
Files.write(file, dataList, Charset.forName("UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The interface & implementation for MyDataWebService:
interface MyDataWebServiceInterface {
List<String> requestData();
}
class MyDataWebService implements MyDataWebServiceInterface {
public MyDataWebService(String request) {
}
#Override
public List<String> requestData() {
return Arrays.asList("foo", "bar");
}
}
And a test using mockito. Note, the checks for existing file and thread sleeping may not be the most elegant thing to do here. If you can afford adding some marker in RequestThread to indicate that the data has been written, it would certainly make the test better and safer (filesystems i/o are sometimes tricky to test).
#RunWith(MockitoJUnitRunner.class)
public class RequestThreadTest {
private static final Path FILE = Paths.get("someDir", "sample");
#Mock
MyDataWebServiceInterface service;
#InjectMocks
MainThreads.RequestThread reqThread = new MainThreads.RequestThread("sample");
#Before
public void setup() throws IOException, InterruptedException {
if (Files.exists(FILE)) {
Files.delete(FILE);
while (Files.exists(FILE)) {
Thread.sleep(50);
}
}
}
#Test
public void shouldWriteFile() throws InterruptedException {
Mockito.when(service.requestData()).thenReturn(Arrays.asList("one", "two"));
reqThread.start();
while (!Files.exists(FILE)) {
Thread.sleep(50);
}
// HERE run assertions about file content
}
}
Now, testing asynchronous code is often more complicated than synchronous because you will often face non-determinist behaviours, timing issues, etc. You may want to set a timeout on your test, but remember: continuous integration tools (jenkins, travis etc.) will often run slower than your machine, it's a common cause of problems, so don't set it too tight. As far as I know there is no "one-fits-all" solution for non-determinist issues.
There's an excellent article about non-determinism in tests by Martin Fowler: https://martinfowler.com/articles/nonDeterminism.html
A distinctive non-answer: in 2018, you don't use "raw" threads any more.
Java has much better abstractions to offer by now, for example the ExecutorService. And guess what: when you have your code submit tasks into such a service, you can probably test it using a same-thread executor service.
Meaning: by using such abstractions and dissecting your delivery into specific services, you might be able to (almost) fully test not only the small units, but also how tasks come into your system and worked on.
In other words: you unit test your "tasks", then you "unit" test the integration of tasks when they go into such an executor. Then you are only left with a bit of real function/integration testing to check that the "true parallel" solution behaves as expected.
Anything else gets complicated quickly. Using real threads in ordinary unit tests can lead to inconsistent behavior, or increased runtimes (like the test waiting for threads to asynchronously doing something).
As in your example: your test would simply sit there and regularly check if the expected file was written with the expected content. Leading to: how long should it wait before failing? Waiting not long enough means that your test will occasionally fail because code sometimes just takes longer. If you wait too long, that adds up to the overall time you need to run your tests. You don't want to end up with hundreds of unit tests were some need 10, 20 seconds because "waiting for other threads".

Thread creation listener

Is it possible to write Thread creation listener in java? For example using aop?!
I mean something like this that if my application creates a thread I would like to register this object in my own table, container or something.
I would create a thread that continously lists all running threads on the JVM.
Then each time it noticies that a new thread has appeared, it would notify in either way a class in your code.
Here are some links about how to list all threads currently running on the JVM :
Get a List of all Threads currently running in Java
Listing All Running Threads
============
A starting code :
ThreadCreationListener.java
public interface ThreadCreationListener {
public void onThreadCreation(Thread newThread);
}
ThreadCreationMonitor.java
public class ThreadCreationMonitor extends Thread {
private List<ThreadCreationListener> listeners;
private boolean canGo;
public ThreadCreationMonitor() {
listeners = new Vector<ThreadCreationListener>();//Vector class is used because many threads may use a ThreadCreationMonitor instance.
canGo = true;
// Initialize the rest of the class here...
}
// Most important methods
public void addListener(ThreadCreationListener tcl) {
listeners.add(tcl);
}
public void removeListener(ThreadCreationListener tcl) {
listeners.remove(tcl);
}
public void run() {
List<Thread> runningThreads;
List<Thread> lastRunningThreads = new ArrayList<>();
while(canGo) {
// Step 1 - List all running threads (see previous links)
// runningThreads = ...
// Step 2 - Check for new threads and notify all listeners if necessary
if (runningThreads.removeAll(lastRunningThreads)==true) {
for(Thread t : runningThreads) {
for(ThreadCreationListener tcl : listeners) {
lastRunningThreads.add(t);
tcl.onThreadCreation(t); //Notify listener
}
}
}
}
}
public void shutdown() {
canGo = false;
}
}
MyThreadInfoConsumer.java
public class MyThreadInfoConsumer implements ThreadCreationListener {
public void onThreadCreation(Thread newThread) {
// Process here the notification...
}
}
Main.java
public class Main {
public static void main(String[] args) {
ThreadCreationMonitor tcm = new ThreadCreationMonitor();
tcm.start();
MyThreadInfoConsumer myTIC = new MyThreadInfoConsumer();
tcm.addListener(myTIC);
// rest of your code...
// Don't forget to call tcm.shutdown() when exiting your application !
}
}
I think this would be possible with AOP (aspectj for instance). But it is still required to create your own Thread and ThreadGroup/Executor types, unless you can recompile the JDK classes with the aspect compiler. Define the pointcut on your thread's start method if you want to register on thread launching or on the createThread of your pool if you want to register on the creation of the thread objects.
The following works only if you recompiled the JDK with the aspect compiler:
All threads are started with Thread.start, so write a pointcut for that method then you can use advices to do what you'd like to. Of course this is not perfect since e.g. a cachedThreadPool executor might not start a new thread for each task, but maybe if you register a pointcut on Runnable.run and Callable.call rather than on Thread.start, that might be sufficient enough.
Perhaps a ThreadGroup is what you need. All Threads are members of a ThreadGroup and when you start a new Thread it is added to the same group as its parent by default.
In theory its possible (but not recommended) to sub-class to be notified when a Thread is added or removed from the group.
It is likely that polling the threads of this groups, or polling all threads is a better solution.

Categories