0

I have following code to test:

Public MyClass() {

    public static final boolean myFunc(int param1, String param2, long param3) {

        SomeInterface var1 = SomeEnumImplementingSomeInterface.INSTANCE;
        SomeOtherInterface var2 = var1.getInstanceOfSomeOtherInterface();

        String str = var2.getValue();

        if (str.equals("ABCD"))
            return true;
        else 
            return false;
    }
}

Is there any way by which I can assign a mocked object to var1 here?

One way around to this I could think of is declare var1 as class variable (it has to be static in this case since the method accessing it is static), and then assign mocked object to it by whiteboxing. But I don't want to change the design just for the sake of testing it.

Please avoid suggesting me a change in the class design.

rajneesh2k10
  • 1,550
  • 3
  • 12
  • 24
  • 1
    Looks like you are trying to test whatever the `var1.getInstanceOfSomeOtherInterface()` method returns. Why do you need to mock the enum? – Bhesh Gurung Feb 19 '13 at 16:21
  • It's a good idea to design classes so they can be easily tested – greuze Feb 19 '13 at 17:02
  • @BheshGurung I'm trying to test the value returned by `var2.getValue()`. I've oversimplified the actual class. Some other values are being passed to this `getValue()` function. – rajneesh2k10 Feb 19 '13 at 18:59

1 Answers1

1

You could use a package or protected method to set var1 value, and in your test, if necessary, you can override your class to set the mock object, similar to this:

public MyClass() {

    public static final boolean myFunc(int param1, String param2, long param3) {

        SomeInterface var1 = getVar1();
        SomeOtherInterface var2 = var1.getInstanceOfSomeOtherInterface();

        String str = var2.getValue();

        if (str.equals("ABCD"))
            return true;
        else 
            return false;
    }

    SomeInterface getVar1() {
        return SomeEnumImplementingSomeInterface.INSTANCE;
    }
}

public MyClassTest {

    private MyClass myClassUnderTest = new MyClass() {
        @Override
        SomeInterface getVar1() {
            return SomeEnumImplementingSomeInterface.INSTANCE;
        }
    } 

    public void testMyFunc() {
        // do test stuff with myClassUnderTest
    }
}
greuze
  • 4,250
  • 5
  • 43
  • 62
  • Thanks for the reply greuze. But I've no access to those interfaces. Those are actually APIs exposed to me. I want to know if there is some way by which I can set the value of var1 with some other value? – rajneesh2k10 Feb 19 '13 at 18:48
  • I don't understand, I didn't change any interface. You mean you can't modify class MyClass? – greuze Feb 22 '13 at 08:22
  • Oh sorry for creating confusion here. I meant I don't want to change the class. `getVar1()` has to be created just for the sake of testing. Is there any other way out? – rajneesh2k10 Feb 22 '13 at 10:06
  • 1
    If you don't want to modify the class, you could copy/paste the functionality to test (very poor design) or modify the bytecodes to set a different value (very poor design too). When you design a class, you should prepare it for being easy testable. If you test based on a concrete implementation, and a concrete assignation in a concrete line, your test will crash when someone modify the class (even if the functionality is still ok, for example changing the variable name). – greuze Feb 26 '13 at 12:17
  • 1
    I recommend that you use a "set" method (with package or protected access), so you have to take care only for behaviour the class should have (not how it does the stuff). If you were using TDD, you should create the test before create the class-to-be-tested, so you would be sure you are testing what the class must do, and not how. – greuze Feb 26 '13 at 12:17
  • Thank you so much. I'll change the design for testing the code. That will be a good move I suppose. – rajneesh2k10 Feb 26 '13 at 12:58