Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Using JUnit to test privately contained List?

Reply
Thread Tools

Using JUnit to test privately contained List?

 
 
kk_oop@yahoo.com
Guest
Posts: n/a
 
      03-01-2005
Hi.

In Java, we have a class MyClass that privately contains an ArrayList
as an attribute called myList. We were looking for a way to enable a
JUnit test case class to call MyClass methods, then check the state of
myList.

Here's a what we are considering:

a. Make a protected method in MyClass called getMyList that returns
myList and performs lazy instantiation (it'll only instantiate myList
the first time it is called but will return myList everytime).
MyClass should only access myList through this getter.

b. Make a test version of MyClass called something like TestMyClass.
Give that a public version of the myList attribute called myTestList.


c. Override getMyList so it will use myTestList instead of myList.

d. The test case class will instantiate TestMyClass, and call its
methods polymorphically through an variable of type MyClass.

e. When the test case wants to check the list values, it will just
cast MyClass back to TestMyClass and access the public myTestList.

The upside of this is that myList gets to remain private in the
production code. The downside is that we are not actually using
myList in the test runs. My thought was that if myTestList is the
same type as myList and the override version of getMyList does exactly
the same thing as the production code's getMyList (except for acting
on the test version of myList), this downside becomes negligible.

Note that we would define TestMyClass as an inner class of the JUnit
test case so it will not have a .java file generated for it.

Any thoughts on this approach? Good? Bad? Recommend a different
approach?

Thanks for any feedback!

Ken

 
Reply With Quote
 
 
 
 
Marcin Grunwald
Guest
Posts: n/a
 
      03-01-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> Hi.
>
> In Java, we have a class MyClass that privately contains an ArrayList
> as an attribute called myList. We were looking for a way to enable a
> JUnit test case class to call MyClass methods, then check the state of
> myList.
>
> Here's a what we are considering:
>
> a. Make a protected method in MyClass called getMyList that returns
> myList and performs lazy instantiation (it'll only instantiate myList
> the first time it is called but will return myList everytime).
> MyClass should only access myList through this getter.
>
> b. Make a test version of MyClass called something like TestMyClass.
> Give that a public version of the myList attribute called myTestList.
>
>
> c. Override getMyList so it will use myTestList instead of myList.
>
> d. The test case class will instantiate TestMyClass, and call its
> methods polymorphically through an variable of type MyClass.
>
> e. When the test case wants to check the list values, it will just
> cast MyClass back to TestMyClass and access the public myTestList.
>
> The upside of this is that myList gets to remain private in the
> production code. The downside is that we are not actually using
> myList in the test runs. My thought was that if myTestList is the
> same type as myList and the override version of getMyList does exactly
> the same thing as the production code's getMyList (except for acting
> on the test version of myList), this downside becomes negligible.
>
> Note that we would define TestMyClass as an inner class of the JUnit
> test case so it will not have a .java file generated for it.
>
> Any thoughts on this approach? Good? Bad? Recommend a different
> approach?
>
> Thanks for any feedback!
>
> Ken


You shouldn't use private members in tests. Tests should be write for class
interfaces.
But theory and practice sometimes differ a lot
By reflection you can get to object private members, in that way you needn't
to modify your class for testing.

--
Cheers
grundig
 
Reply With Quote
 
 
 
 
Daniel Tryba
Guest
Posts: n/a
 
      03-01-2005
(E-Mail Removed) wrote:
[special testcase objects in class]
> Any thoughts on this approach? Good? Bad? Recommend a different
> approach?


IMHO that it would be bad (atleast not good practice). This does however
sounds like a job for reflection.

 
Reply With Quote
 
kk_oop@yahoo.com
Guest
Posts: n/a
 
      03-01-2005

Marcin Grunwald wrote:
> (E-Mail Removed) wrote:
>
>
> You shouldn't use private members in tests. Tests should be write for

class
> interfaces.


What is the alternative? I'm hoping to avoid adding methods to the
production code just to make the private member visible to a test. One
of our challenges is that our code is highly algorithmic, so a single
public method will manipulate a lot of internal state to provide a
result. If I only test the public method and it fails, it will be
difficult to hunt down where it failed without testing internal state
along the way.

Note that this approach would just be done for our class level unit
testing. We would still be using all production code for our higher
level integration testing.

> By reflection you can get to object private members, in that way you

needn't
> to modify your class for testing.


Could you describe how this would work?

Thanks!

Ken

 
Reply With Quote
 
kk_oop@yahoo.com
Guest
Posts: n/a
 
      03-01-2005

Marcin Grunwald wrote:
<snip>

> By reflection you can get to object private members, in that way you

needn't
> to modify your class for testing.


Aha! Based on your input, I looked around and found this article:

http://www.onjava.com/pub/a/onjava/2...eflection.html

Does that cover what you mean?

Thanks again,

Ken

 
Reply With Quote
 
Marcin Grunwald
Guest
Posts: n/a
 
      03-01-2005
(E-Mail Removed) wrote:

>> You shouldn't use private members in tests. Tests should be write for

> class
>> interfaces.

>
> What is the alternative? I'm hoping to avoid adding methods to the
> production code just to make the private member visible to a test. One
> of our challenges is that our code is highly algorithmic, so a single
> public method will manipulate a lot of internal state to provide a
> result.

I assume that your class is quite complicated and large, maybe you should
split it into a few parts and test that parts separately. I know that it
isn't always possible but I think it is worth of trying. But do it only for
better design of your code, not just for testing; good design is more
important than testing.

> If I only test the public method and it fails, it will be
> difficult to hunt down where it failed without testing internal state
> along the way.

You should write tests just for check if it is OK, not for hunting down
bugs. It is always simpler and faster to take debugger if test has failed,
than to write complicated tests. When you test what class is doing (just
interface) not how it is doing (private members) you can easily modify how
it is working and still have correct tests (for example change ArrayList to
LinkedHashMap or HashSet).

>> By reflection you can get to object private members, in that way you

> needn't
>> to modify your class for testing.

>
> Could you describe how this would work?


Example:
MyClass myClass = new MyClass();
try {
Field field = MyClass.class.getDeclaredField("myList");
field.setAccessible(true);
//myList is reference to private member of myClass object
ArrayList myList = (ArrayList)field.get(myClass);
} catch(NoSuchFieldException ex) {
ex.printStackTrace();
} catch(IllegalAccessException ex) {
ex.printStackTrace();
}

--
Cheers
grundig
 
Reply With Quote
 
kk_oop@yahoo.com
Guest
Posts: n/a
 
      03-01-2005

Marcin Grunwald wrote:
> (E-Mail Removed) wrote:
>

<snip>

Thanks!

 
Reply With Quote
 
Andrew McDonagh
Guest
Posts: n/a
 
      03-01-2005
(E-Mail Removed) wrote:
> Hi.


Hi Ken,

>
> In Java, we have a class MyClass that privately contains an ArrayList
> as an attribute called myList. We were looking for a way to enable a
> JUnit test case class to call MyClass methods, then check the state of
> myList.
>


Lets start with a different perpective.

When the public methods of MyClass are invoked, they do something. Some
of them will do something with the ArrayList, others may not.

In either case, its preferable to test the public methods of a class and
use the output from those methods to verify. In the case of MyClass, one
or more public method may manipulate the ArrayList myList, however,
there most be some existing way to verify those changes.


Now these means of verification don't have to be a getter on the
MyClass, it could well be some other interaction that results from the
public methods being invoked, e.g. Listeners being called back, events
generated, etc.

for instance...

MockMyClassListener mockListener = new MockMyClassListener();

MyClass myClass = new MyClass(mockListener);
myClass.addSomethingToMyList("A String");

assertTrue("Listener not called back", mockListener.wasCalled());

or another example ....

MyClass myClass = new MyClass();
myClass.doSomethingWith("A String");

assertTrue("Listener not called back", myClass.hasDoneSomethingWith("A
String"));


So basically today, there must either be
1) something happening when the public methods are called
2) some way of inspecting the state of MyClass after the public methods
are called.

If there isn't then whats the point in having the public method?

So on to your ideas...

> Here's a what we are considering:
>
> a. Make a protected method in MyClass called getMyList that returns
> myList and performs lazy instantiation (it'll only instantiate myList
> the first time it is called but will return myList everytime).
> MyClass should only access myList through this getter.
>
> b. Make a test version of MyClass called something like TestMyClass.
> Give that a public version of the myList attribute called myTestList.
>
> c. Override getMyList so it will use myTestList instead of myList.
>
> d. The test case class will instantiate TestMyClass, and call its
> methods polymorphically through an variable of type MyClass.
>
> e. When the test case wants to check the list values, it will just
> cast MyClass back to TestMyClass and access the public myTestList.
>
> The upside of this is that myList gets to remain private in the
> production code. The downside is that we are not actually using
> myList in the test runs. My thought was that if myTestList is the
> same type as myList and the override version of getMyList does exactly
> the same thing as the production code's getMyList (except for acting
> on the test version of myList), this downside becomes negligible.


This is good techique, one which we use alot when testing classes that
need to do something which is hard to test. For example, if testing a
class that sends messages via RPC, we'd normally create a Mock object
that has the same interface as the real RPC implementation, and get the
class under test to use the mock instead of the real RPC one.

However... the only (potential) problem with creating a protected getXXX
method which your TestableDerived class overrides, is that the
production class must ALWAYS use the getXXX method when wanting to use
the arraylist. Its putting a risk into the class that another developer
will modify MyClass and forget to use the getXXX() method, and reference
the member var arraylist directly.

But don't worry, this is easily solved by slightly changing the
protected method.

In effect the protected method is really a factory method which is
creating an instance of an ArrayList. So if we name it as such, and only
call it once to create mylist (usually at construction time), then the
MyClass internals are free to acces myList list you normally would.

e.g.

public class MyClass {
public MyClass() {
// do usual stuff.
m_myList = createMyList();
}

protected ArrayList createMyList() {
return new Arraylist();
}

public void doSomethingWith(String aString) {
m_myList.add(aString);
}

private List m_myList = null;
}


public class TestableMyClass {

protected ArrayList createMyList() {
return m_listToUseWhenTesting;
}

public List m_listToUseWhenTesting = new Arraylist();

}

>
> Note that we would define TestMyClass as an inner class of the JUnit
> test case so it will not have a .java file generated for it.


Yes this is where we normally put the TestableMyClass as well, at least
until another test suite needs to mock out the same behaviour, then we
make the TestableMyClass a top-level class. It still lives in the
UnitTest source tree though.


Its worth noting that sometimes, using a factory method may not be
appropriate, in which case we use an AbstractFactory pattern to achieve
the same results. The AbstractFactory also means we do not have to
create any TestableDerivedClass in our unit tests, we simply change the
AbstractFactory to return our mockObject instead of a real object.
 
Reply With Quote
 
Andrew McDonagh
Guest
Posts: n/a
 
      03-01-2005
Marcin Grunwald wrote:
> (E-Mail Removed) wrote:
>
>
>>Hi.
>>
>>In Java, we have a class MyClass that privately contains an ArrayList
>>as an attribute called myList. We were looking for a way to enable a
>>JUnit test case class to call MyClass methods, then check the state of
>>myList.
>>
>>Here's a what we are considering:
>>
>>a. Make a protected method in MyClass called getMyList that returns
>>myList and performs lazy instantiation (it'll only instantiate myList
>>the first time it is called but will return myList everytime).
>>MyClass should only access myList through this getter.
>>
>>b. Make a test version of MyClass called something like TestMyClass.
>>Give that a public version of the myList attribute called myTestList.
>>
>>
>>c. Override getMyList so it will use myTestList instead of myList.
>>
>>d. The test case class will instantiate TestMyClass, and call its
>>methods polymorphically through an variable of type MyClass.
>>
>>e. When the test case wants to check the list values, it will just
>>cast MyClass back to TestMyClass and access the public myTestList.
>>
>>The upside of this is that myList gets to remain private in the
>>production code. The downside is that we are not actually using
>>myList in the test runs. My thought was that if myTestList is the
>>same type as myList and the override version of getMyList does exactly
>>the same thing as the production code's getMyList (except for acting
>>on the test version of myList), this downside becomes negligible.
>>
>>Note that we would define TestMyClass as an inner class of the JUnit
>>test case so it will not have a .java file generated for it.
>>
>>Any thoughts on this approach? Good? Bad? Recommend a different
>>approach?
>>
>>Thanks for any feedback!
>>
>>Ken

>
>
> You shouldn't use private members in tests. Tests should be write for class
> interfaces.


Agreed.

> But theory and practice sometimes differ a lot


very true.

> By reflection you can get to object private members, in that way you needn't
> to modify your class for testing.


I'd never suggest anyone uses reflection to aid unit testing. There are
easier ways that do not incur the tight coupling between unit test code
and production code.

If we used reflection to find the myList object within the MyClass
object, then our tests would have to change should we ever decide to
rename the member or change its type, or any number of other refactoring
that may happen over the life time of MyClass.

Its simply a too brittle and bad means of testing.
 
Reply With Quote
 
Andrew McDonagh
Guest
Posts: n/a
 
      03-01-2005
(E-Mail Removed) wrote:
> Marcin Grunwald wrote:
> <snip>
>
>>By reflection you can get to object private members, in that way you

>
> needn't
>
>>to modify your class for testing.

>
>
> Aha! Based on your input, I looked around and found this article:
>
> http://www.onjava.com/pub/a/onjava/2...eflection.html
>
> Does that cover what you mean?
>
> Thanks again,
>
> Ken
>


Ken, reflection as a testing mechanism is a red herring - you'd be best
not going there.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
publicly/privately derived types Jess C++ 3 05-14-2007 07:31 PM
Video Emailing Privately On YouTubes Website Technical Question Heidi Manway Computer Support 1 02-03-2007 05:38 PM
Video Emailing Privately On YouTubes Website Technical Question Heidi Manway Computer Support 0 02-03-2007 05:00 PM
can i pass privately? newbie Microsoft Certification 1 07-19-2004 12:11 AM
test test test test test test test Computer Support 2 07-02-2003 06:02 PM



Advertisments