如何对同步代码进行单元测试
问题描述:
我是Java和junit的新手。我有以下代码,我想测试。如果您能发送关于测试它的最佳方式的想法,请多加谅解。如何对同步代码进行单元测试
基本上,下面的代码是关于从一个集群中选举一个领导者的。领导者持有对共享缓存的锁定,并且领导者的服务可以恢复并处理,如果它以某种方式丢失了缓存上的锁定。
如何确保领导者/线程仍然保持缓存中的锁定,并且另一个线程无法在第一次执行时恢复其服务?
public interface ContinuousService {
public void resume();
public void pause();
}
public abstract class ClusterServiceManager {
private volatile boolean leader = false;
private volatile boolean electable = true;
private List<ContinuousService> services;
protected synchronized void onElected() {
if (!leader) {
for (ContinuousService service : services) {
service.resume();
}
leader = true;
}
}
protected synchronized void onDeposed() {
if (leader) {
for (ContinuousService service : services) {
service.pause();
}
leader = false;
}
}
public void setServices(List<ContinuousService> services) {
this.services = services;
}
@ManagedAttribute
public boolean isElectable() {
return electable;
}
@ManagedAttribute
public boolean isLeader() {
return leader;
}
public class TangosolLeaderElector extends ClusterServiceManager implements Runnable {
private static final Logger log = LoggerFactory.getLogger(TangosolLeaderElector.class);
private String election;
private long electionWaitTime= 5000L;
private NamedCache cache;
public void start() {
log.info("Starting LeaderElector ({})",election);
Thread t = new Thread(this, "LeaderElector ("+election+")");
t.setDaemon(true);
t.start();
}
public void run() {
// Give the connection a chance to start itself up
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
boolean wasElectable = !isElectable();
while (true) {
if (isElectable()) {
if (!wasElectable) {
log.info("Leadership requested on election: {}",election);
wasElectable = isElectable();
}
boolean elected = false;
try {
// Try and get the lock on the LeaderElectorCache for the current election
if (!cache.lock(election, electionWaitTime)) {
// We didn't get the lock. cycle round again.
// This code to ensure we check the electable flag every now & then
continue;
}
elected = true;
log.info("Leadership taken on election: {}",election);
onElected();
// Wait here until the services fail in some way.
while (true) {
try {
Thread.sleep(electionWaitTime);
} catch (InterruptedException e) {}
if (!cache.lock(election, 0)) {
log.warn("Cache lock no longer held for election: {}", election);
break;
} else if (!isElectable()) {
log.warn("Node is no longer electable for election: {}", election);
break;
}
// We're fine - loop round and go back to sleep.
}
} catch (Exception e) {
if (log.isErrorEnabled()) {
log.error("Leadership election " + election + " failed (try bfmq logs for details)", e);
}
} finally {
if (elected) {
cache.unlock(election);
log.info("Leadership resigned on election: {}",election);
onDeposed();
}
// On deposition, do not try and get re-elected for at least the standard wait time.
try { Thread.sleep(electionWaitTime); } catch (InterruptedException e) {}
}
} else {
// Not electable - wait a bit and check again.
if (wasElectable) {
log.info("Leadership NOT requested on election ({}) - node not electable",election);
wasElectable = isElectable();
}
try {
Thread.sleep(electionWaitTime);
} catch (InterruptedException e) {}
}
}
}
public void setElection(String election) {
this.election = election;
}
@ManagedAttribute
public String getElection() {
return election;
}
public void setNamedCache(NamedCache nc) {
this.cache = nc;
}
答
作为替代测试框架(或JUnit的顶部额外的扩展,如果你正在使用的)只是一些普通的旧代码:
- 创建多个线程,并将其应用到这个程序。
- 循环穿过线程并测试每个线程,直到找出谁是领导者。
- 将不同的环境变化(包括时间流逝)应用于程序状态并重做测试。领导者仍然是领导者吗?
- 现在,强迫领导者放弃(杀死那个线程或其他东西)。另一个线程接管了吗?
答
如果您对使用JUnit不太具体,那么您可以使用TestNG框架。他们有多线程支持。
http://today.java.net/article/2003/07/12/multithreaded-tests-junit http://www.junit.org/node/54 – Bozho 2010-05-13 09:41:38