【问题标题】:How can i unittest a method in a inner-class?如何对内部类中的方法进行单元测试?
【发布时间】: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


【解决方案1】:

在分析了您的主类和私有类之后,该私有类不需要是内部类,因为该类与包含它的类没有任何关系:内部类不引用任何封闭类的变量或方法。

最好的解决方案是更改您的设计,将内部类提取到非内部公共类中,然后像往常一样对其进行测试。

如果您不想更改设计或由于某种原因无法更改(即代码可以以某种方式发展或增长,您需要它保持原样),您必须使用更高级的机制像反射一样。在这种情况下,您可以检查以下问题:

How do I test a class that has private methods, fields or inner classes?

【讨论】:

    【解决方案2】:

    我看起来 MemorySampler 不依赖于 UsedMemory 的实例,因此您可以将其设为静态。然后,如果您将访问级别更改为默认而不是私有,您将能够从同一包中的单元测试访问它。

    static class MemorySampler extends TimerTask {
        ...
    }
    

    在你的单元测试类中:

    @Test
    public void test() {
        UsedMemory.MemorySampler sampler = new UsedMemory.MemorySampler("memoryPool");
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多