如何检测是否使用JUnit生成了一个线程?

时间:2016-09-20 19:24:14

标签: java multithreading junit junit4

我正在使用Java 6和Junit 4.12。我试图在JUnit中检测是否从一个类生成了一个线程。在我的班上,我像这样生成线程

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

但是,在我的JUnit测试中,当我尝试获取正在运行的线程列表时,上面的内容从未出现过。以下是我试图获取线程列表的方法

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

有没有更好的方法来列出线程,还是有另一种方法可以检测线程是否产生?

2 个答案:

答案 0 :(得分:0)

看来你过于复杂了。让线程在开始运行时设置一个标志,并让你的单元测试检查该标志,看它是否曾经设置过。

例如,如果多个&#34; myId&#34;值是可能的:创建一个公共静态HashMap(我称之为s_threadFlags),用于映射&#34; myId&#34; Boolean值的关键字,让run()方法设置为&#34; myId&#34;该映射中的值为Boolean.TRUE,并使单元测试类获取该键的值。

线程代码可以是:

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

并且单元测试代码可以简化为:

boolean threadSpawned = (MyThreadClass.s_threadFlags.get(myId) == Boolean.TRUE);

添加:

  • 在单元测试的Before或BeforeClass方法中调用MyThreadClass.initThreadFlags()
  • 在After或AfterClass方法中调用MyThreadClass.clearThreadFlags()以清理。

答案 1 :(得分:0)

向您的班级中注入ThreadFactory并使用 it 创建新主题,而不是调用Thread::new。然后,JUnit测试可以轻松注入自定义ThreadFactory并验证是否要求创建新的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);
        }
    });
}

并自定义滚动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();
    }
}

如果您使用Mockito,则只需使用spy()代替。

在测试中,您可以这样做:

public void test() {

    MyThreadFactory threadFactory = new MyThreadFactory();
    YourClass yourClass = new YourClass(threadFactory);

    yourClass. // invoke method under test

    assertThat(threadFactory.numberOfInvocations()).isEqualTo(1);

}