【发布时间】:2016-05-25 14:28:33
【问题描述】:
我用内部类制作了这个单例。我想对该方法进行单元测试:运行。现在我发现我应该通过反思来做到这一点,但我不知道该怎么做。是否可以为该方法进行单元测试:运行?以及如何?
package monitor;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import com.gesmallworld.magik.commons.runtime.annotations.MagikProc;
import com.gesmallworld.magik.commons.runtime.objects.Char16Vector;
public class UsedMemory{
private static UsedMemory theInstance;
private static synchronized UsedMemory getInstance() {
if( theInstance == null) {
theInstance = new UsedMemory();
}
return theInstance;
}
private Map<String, MemorySampler> MEMORY_SAMPLERS = new Hashtable<String, MemorySampler>();
private MemorySampler getMemorySampler(String memoryPool) {
MemorySampler sampler = MEMORY_SAMPLERS.get(memoryPool);
if (sampler == null) {
sampler = new MemorySampler(memoryPool);
MEMORY_SAMPLERS.put(memoryPool, sampler);
}
return sampler;
}
@MagikProc(name="rw_diag_setupusedmemory")
public static void setupUsedMemory(Object proc, Char16Vector memoryPool, int timer){
new Timer().schedule(getInstance().getMemorySampler(memoryPool.toString()), 0, timer);
}
@MagikProc(name="rw_diag_usedmemory")
public static Char16Vector getUsedMemory(Object proc, Char16Vector memoryPool){
return getInstance().getMemorySampler(memoryPool.toString()).getUsedMemoryString();
}
private class MemorySampler extends TimerTask {
private MemoryPoolMXBean mxbean;
private int byteToMb = 1048576;
private long min = 0;
private long avg = 0;
private long count = 0;
private long max = 0;
public MemorySampler(String memoryPool) {
mxbean = getMemoryPoolMXBean(memoryPool);
}
private Char16Vector getUsedMemoryString(){
long minTemp = min;
long avgTemp = avg;
long maxTemp = max;
min = 0;
avg = 0;
max = 0;
count = 0;
return new Char16Vector(minTemp/byteToMb+"__"+avgTemp/byteToMb+"__"+maxTemp/byteToMb);
}
@Override
public void run() {
long used = mxbean.getUsage().getUsed();
if(min==0 || used < min){
min = used;
}
if(max==0 || used > max){
max = used;
}
if(count==0){
avg = used;
} else {
avg=((avg*count)+used)/(count+1);
}
count +=1;
}
private MemoryPoolMXBean getMemoryPoolMXBean(String pool){
List<MemoryPoolMXBean> mxbean = ManagementFactory.getMemoryPoolMXBeans();
for(MemoryPoolMXBean mPool: mxbean){
if(mPool.getName().equals(pool)){
return mPool;
}
}
return null;
}
}
}
【问题讨论】:
-
最简单的解决方案:首先编写可测试的代码。 (不要把代码放到那个定时器任务中,让它自己工作)
-
附带说明,您的课程不是线程安全的 - 考虑到您使用多个线程,这可能是一个非常糟糕的主意。
-
关于可测试性:(i) 尽可能避免使用单例模式,(ii) 使 MemorySampler 成为包私有的顶级类。优秀的相关阅读:misko.hevery.com/attachments/…(单身人士在第 23 页解决)
标签: java unit-testing singleton inner-classes