0

The question is "simple". Similar to Mockito.verify(myInstance, times(3)), is there anything in any test framework that counts object instantiations?

I mean:

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
}

I hope my example helps to give you an idea of what am I trying to obtain.

Ordiel
  • 2,442
  • 3
  • 36
  • 52
  • 2
    With PowerMockito you can stub/spy constructors. https://stackoverflow.com/questions/13364406/mockito-mock-a-constructor-with-parameter – Erwin Bolwidt Aug 09 '17 at 05:42

3 Answers3

0

I do not know of any framework that provides this functionality, unfortunately. What you can do, however, is modify or override the constructor and finalize methods for a given class and store a counter in a static variable.

public class MyClass {
    public static int instances = 0;

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

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

}

Hope this helps.

Wep0n
  • 392
  • 3
  • 15
  • 1
    @Ordiel https://stackoverflow.com/a/1908870/7591918 Also check this out, I think part 3 and 4 will be especially interesting for you. – Wep0n Aug 09 '17 at 05:38
  • Yup, i thought about that, but it does not helps on classes I cannot control :/ – Ordiel Aug 09 '17 at 05:38
  • Check my comment, you have the best timing ;) – Wep0n Aug 09 '17 at 05:39
  • @Ordiel Have you had any success with the field injection discussed in the article I linked in my first comment? I'm genuinely interested in this now :D – Wep0n Aug 10 '17 at 05:46
  • Hey, not yet, I haven't had the chance to get back to that code yet, nonetheless, I am considering a less mainstream approach to solve this, I will attempt to use AspectJ to add such behavior. – Ordiel Aug 10 '17 at 14:31
0

you can define a static field in your class and increment it in the class constructor like this:

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++;
    }
}

or if you want the counter to be private you can use a public method to return it:

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;
    }
}
Mina
  • 11
  • 4
0

You can use the JDI interface to count objects. It comes with the JDK. To use it include the tools.jar file in your class path. I've written a code example below using 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));
}

To run this code you will need to add the following options to your Java call:

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

This BeyoundJava article gave me the basic idea for this solution.