Unit Testing a Client-Server Application in Java - java

I'm working on a simple client-server application, and I'm supposed to initialize my client and server objects in separate threads. The server contains a database of all of the courses in some specific departments at my university, and the GET request gets all of the classes in the requested department and sends it back to the client. While I was able to test everything perfectly fine in a main method, unit testing was just not working. Below is my code for the unit test:
import client.Client;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import server.Server;
public class ClientServerTest {
private static String file = "";
#BeforeClass
public static void setFile(){
file = System.getProperty("file");
}
#Before
public void startServerTest(){
Thread serverThread = new Thread(() -> {
new Server(file);
});
serverThread.start();
}
#Test
public void getTest(){
Client client = new Client();
Assert.assertTrue(client.submitRequest("GET COM"));
Assert.assertTrue(client.submitRequest("GET MAT"));
Assert.assertTrue(client.submitRequest("GET BIO"))
}
}
When I run the test, the server test passes, I get the following output for the getTest() test:
java.net.ConnectException: Connection refused: connect
I've been looking around trying to find the best way to get unit tests to work with threads, but I can't seem to figure it out. Any help would be most appreciated.

First, as my fellows stated, that's far away from a unit test but an integration or end-to-end test.
The problem with your test might be that some threads outperforms other threads creating randomly failing tests so you need some option to synchronize them.
I can say that it's absolutely possible to do this kind of testing with JUnit but there are some key concepts to put into practice to make such tests, involving multiple threads, reproducible (not flaky) and any useful.
Without seeing the implementation of Server class it's pretty difficult but I try to sum up the hints that hopefully put you on the right track.
First:
Create your Server class and all other dependencies inside the same thread (preferably in the main thread).
public static void main(String[] args) {
Foo otherInstance = new Foo(...);
Bar anotherInstance = new BarImpl(otherInstance,...);
Server server = new Server(otherInstance, anotherInstance);
server.start(); // blocking until app is stopped in a graceful way and where real application logic starts
// not more to do here
}
Important is that constructors must not do any "work" apart from assigning instance variables like this.someVar = someVar. The concept behind that is called dependency injection and makes your life a lot easier especially if you use a library.
Second:
Your app needs hooks, that tests can plug into to intercept your logic, where you can make threads halt and wait for other events happen that are necessary to make your tests work. Where to plug into depends highly on your application. It's most likely necessary to specify different implementations for some classes inside your tests thus differently wiring the app's dependency graph.
To accomplish that synchronizations aids like CountDownLatch are your best friends inside the test class.
#Test
public void someTest() {
// or move the instantiation logic to the #Before setup method
final CountDownLatch isConnected = new CountDownLatch(1);
Foo otherInstance = new Foo(...);
Bar anotherInstance = new BarTestImpl(otherInstance,...);
// here we plug into the connected event
anotherInstance.setConnectionListener(() -> { isConnected.countDown(); }
Server server = new Server(otherInstance, anotherInstance);
server.startAsync(); // not blocking
...
// test logic starting, do some assertions or other stuff
...
// block until connected event is received
isConnected.await(1, TimeUnit.SECONDS);
// do some assertions
assertTrue(server.isConnected());
...
}
This example is scratching on the surface of what is possible and how to leverage this concept for maintaining a high level of automated testing but it should show the idea behind.

Normally a UnitTest should only test a single component. The "Unit".
You whant to do some kind of integration testing. So you have to ensure that every component that you need for your #Test is up an running before #Test is called.
I'm not sure if JUnit is the best framework for this. But you can add a check in the #Before method that will sleep the main thread until the server is running.
For example:
#Before
public void startServerTest(){
Server = new Server();
Thread serverThread = new Thread(() -> {
server.init(file);
});
serverThread.start();
while (!server.isRunning() {
Thread.sleep(1000);
}
}

Related

How should I start server before JUnit test?

Basically I have this JUnit test for my server here:
#Test
public void test() throws UnknownHostException, IOException, ClassNotFoundException
{
Socket socket = new Socket("localhost", 4444);
PrintWriter stringOut = new PrintWriter(socket.getOutputStream(), true);
ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream());
stringOut.println("getMyString");
String myString = (String) oIn.readObject();
assertEquals("myString", myString);
socket.close();
}
But every time I want to run this test, I need to start the server. How should I get it to start automatically (it has to be in another thread of course)
The technical answer could be to make that socket a field in your test class, and then have a #BeforeAll public static void setUp() method that creates the required object once. Or a #Before public void setUp() that starts the server before every test case. And of course, you would need matching #AfterAll resp. #After methods. As the other answer outlines, you can use a ProcessBuilder for example, to start a completely own process.
But then: a "real" unit test should only rely on your source code. A dependency such as here, that requires an external component/service to be available rather renders these functional or integration tests.
So, the real answer would be: step back. Look at your server code, and ask yourself whether you really need to run the whole server in order to tests its parts.
Meaning: in the end, a "server" is about making some "business logic" available to the outter world. Those are two different concerns, and they should be addressed differently.
So: you write unit tests for your business logic that can all be nicely tested without any server around. And then you write more of an integration test that tests whether your server is correctly "coupled" with the business logic part.
In other words: assume your server offers 3 different services, and each one service has multiple parameters, and "paths" of execution. You absolutely do not test all these services, with all paramater variations and all "paths" by going through your server. Instead, you write your code so that you can test each service completely without spinning up the server for each test. And then, when all of that works, you write a few tests that ensure that each service can be called using the server (and there you focus on very different aspects, like: "are the parameters passed to the service showing up *inside", or "are errors within the business logic processed as expected by the server").
Use ProcessBuilder to start the process, and destroy() to destroy it
ProcessBuilder pb = new ProcessBuilder("/path/to/java", "-jar", "your.jar");
pb.directory(new File("preferred/working/directory"));
Process p = pb.start();
Thread.sleep(1000);
// test here
p.destroy()

Is there any test framework or any other way to test async methods in Java?

I have a bunch of async functions in java that I want to test. I would like to have a functionality where the main thread waits until all the tests are done. The method signature of these functions looks like as follows
public class Callback {
public void onSucess(Result result) {
return result.getLastName();
}
}
public class client{
public static void getLastNameAsync(String firstname, Callback cb);
public static void getLastNameAsync(String middlename, Callback cb);
...................................
...................................
...................................
Imagine there are more functions like this
}
I want to be be able to test the client class as follows
public void TestClient(){
Client client = new Client();
client.getLastNameAsync("Brandon", new callback());
client.getLastNameAsync("kyle", new callback());
....................
....................
....................
Imagine I have to test more functions like this
}
countDownLatch seems to be a solution however I need to know the number of method calls I am invoking and even if I do that seems to be a hacky solution because I need to instantiate as below
CountDownLatch latch = new CountDownLatch(#number of methods calls in my TestClient);
The trick again here is knowing #number of methods calls in my TestClient
open to any kind of advice or solution.
Static methods are not your friend. I would use instance classes, and then use an Executor as the means to control whether the execution is synchronous or asynchronous.
For your production code, inject a ThreadPoolExecutor in order for your logic to defer to another thread (or threads). But, in your test case, use a DirectExecutor to execute the logic in the same thread. See the javadoc for java.util.concurrent.Executor
This way, your test code will be far simpler. I'm sure you want to test the logic being called. If you need to test the multi-threadedness of it, you can then start to approach that as well. But if you don't have to, then keeping things simple will help in the test. And static methods don't help with that.

For Junit issue: when test multiple thread

I use JDK ScheduledThreadPoolExecutor to do schdule job. I give simple code as below.
class Job implements Callable<Void>{
public Long id;
#Override
public Void call() throws Exception {
if (!isOk(id)) {
return null;
}
_context.exe(id);
return null;
}
void setId(Long id) {
this.id = id;
}
}
Every time i add this job to schedule service:
public void schedule() {
Job job = new Job();
job.setId(1L);;
_scheduledExecutor.schedule(job, 1000, TimeUnit.MILLISECONDS) ;
}
this job will delay call context's exe method.
My Question: I want assert _context's exe method called or not? How can I do this?
What I do currently, I try to add log in call() method and verify UT by my eyes.
PS: For this UT, I also try to mock _context's exe method, but job run in other thread, So I cannot assert it in currently thread. anyone have idea to help me write assert for this case?
Currently I do below way, but I still think there better solution for this, Just I don't known.
_context is instance of Context, I extend from this class.
public class UTContext extends Context {
public UTTestCase utTestCase ;
#Override
public void exe(Long id) {
utTestCase.setIsCall(true);
}
public void setUtTestCase(UTTestCase utTestCase) {
this.utTestCase = utTestCase;
}
}
Then I will assert isCall var in UT.
Is any one have good idea for this , pls give me answer. Thank you very much.
You are testing a piece of the middle of the call hierarchy, namely the thread creator/dispatcher code. That means you have to drive the code from the top and test either from the top or the bottom. There are several patterns for how you do that.
Either you instrument the bottom (exe(id)) or you measure from the top. With the scheduling delay, measuring from the top becomes very difficult.
Does exe() have side effects? Is that side effect testable from your test code? Can you infer the operation of one invocation of exe()? Can you infer the invocation of more than one? If the answer to any of these is "no", then you will have to go further.
#RamonBoza has provided a good solution.
You could also create a testable version of class Job, thus:
class JobUT extends Job {
#Override
public Void call() throws Exception {
Void result = super.call();
// Report error if wrong return result
}
}
(I know there are problems with the above code as Void is not being handled properly. I'm not in a position to refactor your code.)
You may also achieve the same objective using Aspect Oriented Programming, where you intercept the call after it has completed and perform the same testing.
For asserting on multithreading I usually create 'N' threads, and assign a different value to set for each thread.
Then join them all and at the end just check if the data of each thread is ¿stored? for example.
Imagine, you create 1000 threads that stores an integer to a database, so after those 1000 threads has finished you have to check if in the database all the data is stored.
A more hard kind of test is for integration test and shall be perform with different scenarios and middleware (OpenNebula, Amazon cloud, etc).
After server day, I know how to verify it now. I attached other question for reference:
Assert times of expectLastCall
Service service = EasyMock.createMock(Service.class);
service.applyInitialDump(entities);
EasyMock.expectLastCall().times(100);
processor.processInitialDump(entities)
EasyMock.verify(service);

JUnit Test of Code that uses GAE/J URLFetchServiceFactory.getURLFetchService()

I've got some code I'm deploying to Google App Engine - Java (GAE/J) that makes use of the URLFetchService. I'd like to use JUnit to test this code. Per the testing documentation, it appears I should have a test that uses their LocalURLFetchServiceTestConfig class ROUGHLY as follows:
public class MyRemoteServiceTests {
private static final LocalURLFetchServiceTestConfig urlConfig = new LocalURLFetchServiceTestConfig();
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(urlConfig);
#Before
public void setUp() throws Exception {
service = new SampleService();
helper.setUp();
}
#After
public void tearDown() throws Exception {
service = null;
helper.tearDown();
}
#Test
public void testThatCallsCodeThatUsesUrlFetch() {
Object data = service.getRemoteDataUsingUrlFetch("foo", "bar");
Assert.assertNotNull(data);
}
}
I'm finding that this test continues to fail despite using the "helper" as suggested in the GAE/J documentation on testing: "The API package 'urlfetch' or call 'Fetch()' was not found.".
I was assuming that using the "helper" would somehow setup the GAE environment such that when I call URLFetchServiceFactory.getURLFetchService() from within my getRemoteDataUsingUrlFetch method, the interface returned would be an instance of LocalURLFetchService that would just "work" but that seems NOT to be the case.
How can I test this code?
Am I missing something? (I'm pretty new to GAE...)
Do I have to refactor my getRemoteDataUsingUrlFetch so that it doesn't use URLFetchServiceFactory.getURLFetchService() because that makes it untestable locally??? (That sounds like it would really suck...)
Any help/suggestions much appreciated!
Actually, it turns out my problem was failure to include two additional jars that ARE mentioned on the Local Unit Testing page of the documentation. RTM FTW!
appengine-local-runtime.jar
appengine-api-stubs.jar
afaik, the LocalURLFetchService doesn't configure the GAE like you expect. It is more of a way to fetch URL from the local dev and then process the contents however. (Similarly even the LocalDatastoreService and LocalMemcacheService operate on isolated spaces within the test environment)
One way to test your code is to refactor the getRemoteDataUsingUrlFetch() to take maybe the contents of the Url response. somewhat like,
URLFetchResponse resp = LocalURLFetchService.fetch(status, request)
getRemoteDataUsingUrlFetch(foo, bar, resp)

How do I write a JUnit test case to test threads and events

I have a java code which works in one (main) thread. From the main thread, i spawn a new thread in which I make a server call. After the server call is done, I am doing some work in the new thread and after that the code joins the main thread.
I am using eclipse Jobs to do the server call.
I want to know, how do I write a JUnit test case for this.
You may need to restructure your code so that it can be easily tested.
I can see several distinct areas for testing:
Thread Management code: the code that launches the thread(s) and perhaps waits for results
The "worker" code run in the thread
The concurrency issues that may result when multiple threads are active
Structure your implementation so that Your Thread Management code is agnostic as to the details of the Worker. Then you can use Mock Workers to enable testing of Thread Management - for example a Mock Worker that fails in certain ways allows you to test certain paths in the management code.
Implement the Worker code so that it can be run in isolation. You can then unit test this independently, using mocks for the server.
For concurrency testing the links provided by Abhijeet Kashnia will help.
This is what I created ConcurrentUnit for. The general usage is:
Spawn some threads
Have the main thread wait or sleep
Perform assertions from within the worker threads (which via ConcurrentUnit, are reported back to the main thread)
Resume the main thread from one of the worker threads once all assertions are complete
See the ConcurrentUnit page for more info.
I'm guessing that you may have done your mocking code and may want a simple integration test to ensure that that your server call works.
One of the difficulties in testing threads comes from their very nature - they're concurrent. This means that you're force into writing JUnit test code that is forced to wait until your thread has finished its job before testing your code's results. This isn't a very good way of testing code, and can be unreliable, but usually means that you have some idea about whether you code is working.
As an example, your code may look something like:
#Test
public void myIntegrationTest() throws Exception {
// Setup your test
// call your threading code
Results result = myServerClient.doThreadedCode();
// Wait for your code to complete
sleep(5);
// Test the results
assertEquals("some value",result.getSomeValue());
}
private void sleep(int seconds) {
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I really don't like doing this and prefer mocks and agree with the other answers. But, if you need to test your threads, then this is one approach that I find works.
When your only problem is waiting for the result, use ExecutorService for spawning your threads. It can accept work jobs both as Runnable and Callable. When you use the latter, then you are given a Future object in return, that can be used to wait for the result. You should consider using ExecutorService anyway, as from what I understand, you create many threads, and this is a perfect use case for executor services.
class AnyClass {
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
public List<Future<Integer>> anyMethod() {
List<Future> futures = new ArrayList<>();
futures.add(threadPool.submit(() -> {
// Do your job here
return anyStatusCode;
}));
futures.add(threadPool.submit(() -> {
// Do your other job here
return anyStatusCode;
}));
return futures;
}
}
And the test class:
class TestAnyClass {
#Test
public void testAnyMethod() {
AnyClass anyObject = new AnyClass();
List<Future<Integer>> futures = anyObject.anyMethod();
CompletableFuture[] completable = futures.toArray(new CompletableFuture[futures.size()]);
// Wait for all
CompletableFuture.allOf(completable).join();
}
}
I suggest you use a mocking framework, to confirm that the server call was indeed made. As for the thread unit testing: Unit testing multithreaded applications
The resources provided by Abhijeet Kashnia may help, but I am not sure what you are trying to achieve.
You can do unit testing with mocks to verify your code, that won't test concurrency but will provide coverage.
You can write an integration test to verify that the threads are being created and joined in the fashion you expect.However this will not guarantee against concurrency problems. Most concurrent problems are caused by timing bugs which are not predictable and thus can't be tested for accurately.
Here is my solution to test asynchrone method which used thread.start:
public class MyClass {
public void doSomthingAsynchrone() {
new Thread(() -> {
doSomthing();
}).start();
}
private void doSomthing() {
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
ArgumentCaptor<Runnable> runnables = ArgumentCaptor.forClass(Runnable.class);
#InjectMocks
private MyClass myClass;
#Test
public void shouldDoSomthingAsynchrone() throws Exception {
// create a mock for Thread.class
Thread mock = Mockito.mock(Thread.class);
// mock the 'new Thread', return the mock and capture the given runnable
whenNew(Thread.class).withParameterTypes(Runnable.class)
.withArguments(runnables.capture()).thenReturn(mock);
myClass.doSomthingAsynchrone();
runnables.getValue().run();
/**
* instead of 'runnables.getValue().run();' you can use a real thread.start
*
* MockRepository.remove(Thread.class);
* Thread thread = new Thread(runnables.getValue());
* thread.start();
* thread.join();
**/
verify(myClass, times(1)).doSomthing();
}
}

Categories