如何编写创建新线程的单元测试

时间:2015-02-09 16:17:03

标签: java multithreading junit mockito

我有以下测试方法:

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()
    }
}

我需要检查那是被调用的方法

alternator.set(false);

我该怎么做?

2 个答案:

答案 0 :(得分:0)

不是直接启动线程,而是传入"执行器"实例

例如......

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);
    }
}

现在你可以更轻松地测试......

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);
    }
}

(没试过编译这个,所以如果有任何错误,我道歉!!)

答案 1 :(得分:0)

虽然非常推荐Bret's post传递执行程序,但您可以使用timeout()模拟验证设置来测试异步条件。

verify(alternator, timeout(500)).set(false);

请注意,这必然会增加测试的瑕疵(即代码通过时测试失败的可能性)。如果具有合理的超时值,那么该薄脆度应该可以忽略不计,但如果您将其作为核心测试基础架构的一部分,则可以考虑重构以允许在测试中同步执行。