I have following method for test:
public class classToTest{
#Autowired
private Alternator alternator;
public void methodToTest(){
Thread t = new Thread(new Runnable() {
public void run() {
while(true) {
if(alternator.get()) {
System.out.print("Hello");
alternator.set(false);
}
}
}
};
t.start()
}
}
I need to check that was invoked method
alternator.set(false);
How can I do it?
Instead of starting a thread directly, can you pass in an "Executor" instance?
For example...
public class ClassToTest{
#Autowired
private Alternator alternator;
#Autowired #Qualifier("myExecutor")
private java.util.concurrent.Executor executor;
public void methodToTest() {
Runnable runnable = new Runnable() {
public void run() {
while(true) {
if(alternator.get()) {
System.out.print("Hello");
alternator.set(false);
}
}
};
executor.execute(runnable);
}
}
Now you can test this easier...
public class ClassToTestTest {
...
#Before
public void setup() {
alternator = mock(Alternator.class);
executor = mock(Executor.class);
obj = new ClassToTest();
ReflectionTestUtils.setField(obj, "alternator", alternator);
ReflectionTestUtils.setField(obj, "executor", executor);
}
#Test
public void shouldStartRunnable() {
obj.methodToTest();
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(executor).execute(runnableCaptor.capture());
Runnable runnable = runnableCaptor.getValue();
// Now test your actual "runnable"...
when(alternator.get()).thenReturn(true);
runnable.run();
verify(alternator).set(false);
}
}
(Have not tried to compile this, so I apologise if there are any mistakes!!)
Though Bret's post of passing in an executor is very much recommended, you can use the timeout() mock verification setting to test for asynchronous conditions.
verify(alternator, timeout(500)).set(false);
Note that this will necessarily increase the flakiness of your test (i.e. the likelihood that the test fails when the code passes). With a sensible timeout value, that flakiness should be negligible, but if you're making this a part of your core test infrastructure you may consider refactoring to allow for synchronous execution in the test.
Related
I have a class that starts multiple threads which all run while(true) loops. Is it possible to have an Assert statements on the state of a test after it has run for a certain amount of time?
The Timeout functionality would work, if it didn't fail the test.
This is a contrived example to show what I'm trying to do. The test is at the bottom.
class RunProgram {
private DataClass dataClass = new DataClass();
private Thread1 thread1 = new Thread1(dataClass);
void startThis() {
ExecutorService pool = Executors.newFixedThreadPool(5);
try {
pool.execute(thread1);//Thread 1
//... more threads with while loops
runMainThread(dataClass);
} finally {
pool.shutdown();
}
}
void runMainThread(DataClass data1){
while(true){
dataClass.setInternalDataInt(20);
//do stuff
}
}
public Thread1 getThread1(){
return this.thread1;
}
}
class Thread1 implements Runnable{
private DataClass dataClass;
Thread1(DataClass dataClass){
this.dataClass = dataClass;
}
public void run() {
dataClass.setInternalDataInt(10);
while (true) {
//dostuff
}
}
public DataClass getDataClass(){
return dataClass;
}
public void setDataClass(DataClass dataClass){
this.dataClass = dataClass;
}
}
class DataClass {
private int internalDataInt;
public int getInternalDataInt(){
return this.internalDataInt;
}
public void setInternalDataInt(int internalDataInt){
this.internalDataInt = internalDataInt;
}
}
class Tests{
#Test
public void stateOfThread1() {
RunProgram runProgram = new RunProgram();
runProgram.startThis();
//Run above for 100 millisecond and then end
Assertions.assertEquals(runProgram.getThread1().getDataClass().getInternalDataInt(), 20);
}
}
Found what I was looking for.
Use a ScheduledExecutorService:
An ExecutorService that can schedule commands to run after a given
delay, or to execute periodically.
RunProgram runProgram = new RunProgram();
ScheduledExecutorService testExecutor = Executors.newScheduledThreadPool(1);
Future future = testExecutor.submit(runProgram);
Thread.sleep(500);
future.cancel(true);
I am testing a simple multithread code using EasyMock:
source code:
public class EasyMockTest {
ExecutorService executorService;
TestObject testObject;
public EasyMockTest(ExecutorService executorService, TestObject testObject)
{
this.executorService = executorService;
this.testObject = testObject;
}
public void test()
{
try
{
executorService.submit(() ->{
testObject.doSomething();
});
}
catch(RejectedExecutionException ex)
{
}
}
}
public class TestObject {
public void doSomething()
{
}
}
Test code with EasyMock:
public class EasyMockTest_test {
private TestObject testObject;
private ExecutorService executorService;
private EasyMockTest easyMockTest;
#Before
public void setUp()
{
executorService = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1));
testObject = EasyMock.createMock(TestObject.class);
easyMockTest = new EasyMockTest(executorService, testObject);
}
#Test
public void test_easyMockTest()
{
testObject.doSomething();
EasyMock.expectLastCall().andAnswer(new IAnswer<Void>(){
#Override
public Void answer() throws Throwable {
Thread.sleep(100);
return null;
}}).times(2);
EasyMock.replay(testObject);
easyMockTest.test();
easyMockTest.test();
easyMockTest.test();
EasyMock.verify(testObject);
}
}
I think in this case testObject.doSomething() should only be called twice. Since thread pool has one thread and queue size is one, and I let first two thread sleep. So when I submit three task, the third one should be rejected and the first two should be called. But when I run this code
there is error:
java.lang.AssertionError:
Expectation failure on verify:
TestObject.doSomething(): expected: 2, actual: 1
at org.easymock.internal.MocksControl.verify(MocksControl.java:225)
at org.easymock.EasyMock.verify(EasyMock.java:2007)
...
This means the method is only called once, which i can't understand.
I also tried comment Thread.sleep(100); this times actual calling times becomes 2, butI think it should be 3 since no thread is sleeping.
Then I tried move .times() position like this:
EasyMock.expectLastCall().times(2).andAnswer(new IAnswer<Void>(){
#Override
public Void answer() throws Throwable {
Thread.sleep(100);
return null;
}});
This time error becomes:
java.lang.AssertionError: Expectation failure on verify:
TestObject.doSomething(): expected: 3, actual: 2
Why result is expecting 3 when i give it 2?
Sorry I am not expert on EasyMock, really appreciate if someone can help.
Nothing is making sure your tasks are executed before the verify is reached. You need something to pace the execution.
This works:
#Test
public void test_easyMockTest() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
testObject.doSomething();
EasyMock.expectLastCall().andAnswer(new IAnswer<Void>(){
#Override
public Void answer() throws Throwable {
latch.countDown();
return null;
}}).times(2);
EasyMock.replay(testObject);
easyMockTest.test();
easyMockTest.test();
easyMockTest.test();
latch.await(1, TimeUnit.SECONDS);
EasyMock.verify(testObject);
}
Here I am assuming that you really want a RejectedExecutionException to be caught and ignored.
I’m using Java 6 and Junit 4.12. I’m trying to detect in JUnit if a thread was spawned from a class. In my class, I spawn the thread like so
final Thread deletethirdpartyClassThread = new Thread(new Runnable(){
#Override
public void run()
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOG.error(e.getMessage(), e);
}
final String threadName = "deletethirdpartyClass:" + myId;
Thread.currentThread().setName(threadName);
m_thirdpartySvc.deleteObject(myId);
}
});
deletethirdpartyClassThread.start();
However, in my JUnit test, when I try and get a list of running threads, the above never shows up. Here is how I’m trying to get the list of threads
boolean threadSpawned = false;
final Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (final Thread t : threadSet) {
if (StringUtils.equals(t.getName(), "deletethirdpartyClass:" + myId))
{
threadSpawned = true;
break;
} // if
} // for
Is there a better way to list the threads or is there another way I can detect the thread was spawned?
Inject a ThreadFactory into your class and use it to create new threads instead of calling Thread::new. A JUnit test can then easily inject a custom ThreadFactory and verify whether it was asked to create a new Thread.
private final ThreadFactory threadFactory;
private final Thread deletethirdpartyClassThread;
public YourClass(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
deletethirdpartyClassThread = threadFactory.newThread(new Runnable(){
#Override
public void run()
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOG.error(e.getMessage(), e);
}
final String threadName = "deletethirdpartyClass:" + myId;
Thread.currentThread().setName(threadName);
m_thirdpartySvc.deleteObject(myId);
}
});
}
and a custom rolled ThreadFactory :
class MyThreadFactory implements ThreadFactory {
private AtomicInteger invocationCounter = new AtomicInteger();
#Override
public Thread newThread(Runnable runnable) {
invocationCounter.incrementAndGet();
return new Thread(runnable);
}
public int numberOfInvocations() {
return invocationCounter.get();
}
}
If you use Mockito, you could simply use a spy() instead.
In a test you can then do this :
public void test() {
MyThreadFactory threadFactory = new MyThreadFactory();
YourClass yourClass = new YourClass(threadFactory);
yourClass. // invoke method under test
assertThat(threadFactory.numberOfInvocations()).isEqualTo(1);
}
It seems you are overcomplicating this. Just have the thread set a flag when it starts running and have your unit test check that flag to see if it was ever set.
For example, if multiple "myId" values are possible: create a public static HashMap (I'll call it s_threadFlags) that is used to map a "myId" key to a Boolean value, have the run() method set its "myId" value in that map to Boolean.TRUE, and have the unit test class get the value of that key.
The thread code could be:
public static Map s_threadFlags;
public static void clearThreadFlags() { s_threadFlags = null; };
public static void initThreadFlags() { s_threadFlags = new HashMap(); };
final Thread deletethirdpartyClassThread = new Thread(new Runnable(){
#Override
public void run()
{
if (s_threadFlags != null) {
s_threadFlags.put(myId, Boolean.TRUE);
}
m_thirdpartySvc.deleteObject(myId);
}
});
deletethirdpartyClassThread.start();
and the unit test code could be reduced to:
boolean threadSpawned = (MyThreadClass.s_threadFlags.get(myId) == Boolean.TRUE);
with the addition of:
A call to MyThreadClass.initThreadFlags() in the unit test's Before or BeforeClass method
A call to MyThreadClass.clearThreadFlags() in the After or AfterClass method, to clean up.
I want to test the code below with Mockito
#Override
public void getSessionList(final int carId, final ResultCallback<List<Session>> callback) {
jobExecutor.execute(new Runnable() {
#Override
public void run() {
List<SessionEntity> sessions = IDataStore.getSessionList(carId);
final List<Session> sessionList = new ArrayList<>();
if (sessions != null) {
for (SessionEntity entity : sessions) {
sessionList.add(mapper.transform(entity));
}
uiThread.post(new Runnable() {
#Override
public void run() {
if (callback != null) {
callback.onResult(sessionList);
}
}
});
}
}
});
}
I tried to do something like this, but my verify methods will be executed early than runnable.
Thread.sleep() works well for the first two verify, but how to test the result from callback.onResult which will be executed in the main thread?
private Repository repository // not mocked
#Mock
private IDataStore dataStore;
#Mock
private DataToDomainMapper dataToDomainMapper;
#Mock
private ResultCallback resultCallback;
#Test
public void testGetSessionListCallbackSuccess(){
List<SessionEntity> sessionEntities = Arrays.asList(sessionEntity, sessionEntity, sessionEntity);
given(dataStore.getSessionList(anyInt())).willReturn(sessionEntities);
given(dataToDomainMapper.transform(any(SessionEntity.class))).willReturn(session);
repository.getSessionList(1, resultCallback);
verify(dataStore).getSessionList(anyInt());
verify(dataToDomainMapper, times(3)).transform(any(SessionEntity.class));
verify(resultCallback).onResult(any(List.class));
}
Check out tool for testing async methods called Awaitility. Very handy tool, saved me a lot of time on testing async methods.
I believe you can move anonymous Runnable to inner (or nested) class and split testing on two parts: check that jobExecutor started execution with corresponding class instance and check that run() method of your inner/nested class works as you expect
I am trying to have a bunch of runnable threads that can be started one at a time.
Something like
First(new Thread() {
public void run() {
//do something
}
});
Is what I'm trying to do impossible?
You can use a single threaded Executor
ExecutorService service = Executors.newSingleThreadedPool();
service.submit(runnable1);
service.submit(runnable2);
service.submit(runnable3);
i want to have several runnables in one thread. they will be doing different things at different times.
This sounds like a bad design to me. If your class is doing different things at different times then it should be split into different classes.
If you are talking about re-using the same background thread to do different things, then I would use a single threaded pool as in #Peter's answer:
private ExecutorService threadPool = Executors.newSingleThreadedPool();
...
threadPool.submit(new First());
threadPool.submit(new Second());
threadPool.submit(new Third());
...
// when you are done submitting, always shutdown your pool
threadPool.shutdown();
The First, Second, and Third classes would implement Runnable. They can take constructor arguments if they need to share some state.
Yes, just have multiple private methods:
public class FirstCaller {
private void method1() { }
private void method2() { }
private void method3() { }
public void someMethod() {
First(new Thread() {
public void run() {
//do something
method1();
method2();
method3();
}
});
}
}
OR as pointed out by Ted Hopp
public class FirstCaller {
public void someMethod() {
new First(new Thread() {
private void method1() { }
private void method2() { }
private void method3() { }
public void run() {
//do something
method1();
method2();
method3();
}
});
}
}
If you want to start a few threads at the same time CountDownLatch is what you need. See an example here: http://www.javamex.com/tutorials/threads/CountDownLatch.shtml.
Are you trying to execute multiple runnables sequentially in a single Thread? One after the other?
public class MultiRunnable implements Runnable {
private Runnable runnable1;
private Runnable runnable2;
public MultiRunnable(Runnable runnable1, Runnable runnable2) {
this.runnable1 = runnable1;
this.runnable2 = runnable2;
}
#Override
public void run() {
runnable1.run();
runnable2.run();
}
}
You could then call (new Thread(new MultiRunnable(... , ...))).start();
This will execute the first Runnable first, and when that is finnished it will execute the second.
Or generalised to more Runnables:
import java.util.Arrays;
import java.util.List;
public class MultiRunnable implements Runnable {
private List<Runnable> runnables;
public MultiRunnable(Runnable... runnables) {
this.runnables = Arrays.asList(runnables);
}
public MultiRunnable(List<Runnable> runnables) {
this.runnables = runnables;
}
#Override
public void run() {
for(Runnable runnable : runnables)
runnable.run();
}
}
The easiest thing to do is to define several Thread subclass instances and call the appropriate one depending on what you are trying to do.
However, if you really need a single Thread object that behaves differently in different circumstances, you can define a Thread subclass that has a state variable for controlling what it does.
class MyThread extends Thread {
public enum Action { A, B, C }
private Action mAction;
public void run() {
if (mAction == null) {
throw new IllegalStateException("Action must be specified");
}
switch (mAction) {
case A:
methodA();
break;
case B:
methodB();
break;
case C:
methodC();
break;
}
}
public void setAction(Action action) {
if (action == null) {
throw new IllegalArgumentException("Action cannot be null");
}
mAction = action;
}
private void methodA() { ... }
private void methodB() { ... }
private void methodC() { ... }
}
You could then create your thread and before calling start(), call setAction, passing one of the Action values.
As an alternative to a state variable, the run() method could examine external variables to determine the choice of action. Whether this makes sense (and whether it would be better) depends on your application.