【问题标题】:Java Testing: how to count object instantiation?Java 测试:如何计算对象实例化?
【发布时间】:2017-08-09 05:28:14
【问题描述】:

问题很“简单”。类似于Mockito.verify(myInstance, times(3))在任何测试框架中是否有任何计算对象实例化的东西?

我的意思是:

class Obj {
    public void a() {
        new Obj();
    }
}

@Test
@PrepareInstantiationCounter(Obj.class) // <-- this does not exists. I need it
...test... {
    new Obj().a();
    InstantiationCounters.countOf(Obj.class) // This also does not exists, I would expect 2
}

我希望我的示例可以帮助您了解我想要获得什么。

【问题讨论】:

标签: java testing instantiation


【解决方案1】:

不幸的是,我不知道有任何框架提供此功能。 但是,您可以做的是修改或覆盖构造函数并为给定类完成方法,并将计数器存储在静态变量中。

public class MyClass {
    public static int instances = 0;

    public MyClass(/*Args*/){
        ...
        MyClass.instances++;
    }

    @Override
    protected void finalize() {
        super.finalize();
        --MyClass.instances;
    }

}

希望这会有所帮助。

【讨论】:

  • @Ordiel stackoverflow.com/a/1908870/7591918 也看看这个,我认为第 3 部分和第 4 部分对你来说会特别有趣。
  • 是的,我想过,但它对我无法控制的课程没有帮助:/
  • 查看我的评论,你有最好的时机;)
  • @Ordiel 您在我在第一条评论中链接的文章中讨论的现场注入是否取得了成功?我现在真的对此很感兴趣:D
  • 嘿,还没有,我还没有机会回到那个代码,不过,我正在考虑一种不太主流的方法来解决这个问题,我会尝试使用 AspectJ 来添加这样的行为。
【解决方案2】:

你可以在你的类中定义一个静态字段并在类构造函数中增加它,如下所示:

class MyClass
{
    public static void main (String[] args)
    {
        obj test=new obj();
        System.out.print(obj.counter); //the result will be 1
    }
}

class obj{
    static int counter=0;
    obj(){
        counter++;
    }
}

或者如果您希望计数器是私有的,您可以使用公共方法返回它:

class MyClass
{
    public static void main (String[] args)
    {
        obj test=new obj();
        System.out.print(obj.numberOfInstances()); //the result will be 1
    }
}

class obj{
    private static int counter=0;
    obj(){
        counter++;
    }
    public static int numberOfInstances(){
        return counter;
    }
}

【讨论】:

    【解决方案3】:

    您可以使用 JDI 接口对对象进行计数。它随 JDK 一起提供。要使用它,请在类路径中包含 tools.jar 文件。我在下面使用 JUnit 4 编写了一个代码示例。

    public class MarsRover {
        public String toString() {
            return "I'm a cool robot";
        }
    }
    
    private static VirtualMachine vm;
    
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
        List<AttachingConnector> acl = vmm.attachingConnectors();
    
        for(AttachingConnector ac: acl) {
            if(ac.transport().name().equals("dt_socket")) {
                Map<String, Connector.Argument> arg = ac.defaultArguments();
                arg.get("port").setValue("3001");
                arg.get("timeout").setValue("30");
    
                vm = ac.attach(arg);
            }
        }
    }
    
    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        vm.dispose();
    }
    
    public static long[] getObjectCount(Class<?> c) {
        return vm.instanceCounts(vm.classesByName(c.getName()));
    }
    
    @Test
    public void test() {
        final long[] objectCount;
        final List<MarsRover> mrArray = Arrays.asList(new MarsRover(), new MarsRover(), new MarsRover());
        objectCount = getObjectCount(MarsRover.class);
        assertThat(objectCount.length, is(1));
        assertThat(objectCount[0], is(3L));
    }
    

    要运行此代码,您需要在 Java 调用中添加以下选项:

    -Xrunjdwp:transport=dt_socket,address=3001,server=y,suspend=n
    

    BeyoundJava article 给了我这个解决方案的基本思路。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-04
      • 2013-03-29
      • 2014-09-25
      • 2011-06-05
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多