4

Have created an android test project and currently trying to write android unit tests

now if you have a bunch of classes whose methods you are trying to test and you've been good and applied the principle of least access and made all your member variables private how do you then write effective unit tests?

In other words, my unit tests sit in a class outside of the class i am trying to test, so I can't access any of the member variables in my assert statements

is there a workaround for this scenario where you want access to everything for testing purposes

please don't tell me i have to write getters and setters for every member variable just so I can write some unit tests

(thinking about it, this is more a Java question than an android specific question)

bph
  • 10,728
  • 15
  • 60
  • 135

2 Answers2

1

Interesting question... Although you might have to write getters/setters for every member variable. It could be worthwhile to put them inside a subclass that you only use for your testing, so you can easily preserve encapsulation in your production code.

That's the best solution I can think of.

EDIT: Or you could make a duplicate class for testing, where you do a quick replace all " private " with " public ".

paulrehkugler
  • 3,241
  • 24
  • 45
  • hmmm - this must be so common as to be a 'pattern' of sorts - hopefully there will be a smart way to solve it without reams of boilerplate.. I have to admit I had considered a quick search and replace but thats a bit smelly – bph Sep 14 '12 at 16:02
  • 1
    @Hiett agreed. There are some interesting answers in this question: http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class-with-private-methods-using-junit – paulrehkugler Sep 14 '12 at 16:09
  • i think that question link will keep me going for a while - many thanks for digging it out... – bph Sep 14 '12 at 16:11
1

If you really don't want to write getters and you want to validate field variables you can still access class field variables via reflection and make assertions against them like so:

Target Class:

public class TestMe{
    private String value = null;

    public void update(){
        value = "hello";
    }
}

Test:

public class TestMeTest {

    @Test
    public void testUpdate() throws NoSuchFieldException, IllegalAccessException {

        TestMe testMe = new TestMe();

        assertNull(getField(testMe, "value"));

        testMe.update();

        assertEquals("hello", getField(testMe, "value"));

    }

    private Object getField(Object root, String name) throws NoSuchFieldException, IllegalAccessException {

        Field field = root.getClass().getDeclaredField(name);
        field.setAccessible(true);

        Object value = field.get(root);

        field.setAccessible(false);

        return value;
    }
}
John Ericksen
  • 10,995
  • 4
  • 45
  • 75
  • do you actually use this or would you just write getters? - i guess your moving a bunch of potential errors being spoted from compile time to runtime – bph Sep 17 '12 at 14:03
  • Personally, I would write getters for the fields you want to access. Using reflection, especially with string keys can be brittle. This is possible and under your requirements may be the best of all evils. – John Ericksen Sep 17 '12 at 14:47
  • Also, using this technique you're moving potential errors from compile time to unit test runtime, which, in the case of error, should prevent you from introducing these bugs into your application's runtime. – John Ericksen Sep 17 '12 at 14:59