A central part in OOP (Object Oriented Programming) model is
encapsulation which hinders the external usage of some of the object’s components, such
as its methods and data. Some OOP languages do not have real encapsulation,
Python is an example of this but there is a loose agreement that internal data
that begins with two underscores should not be accessed directly.
When it comes to unit testing such objects it can be quite
tempting to check that the accessible methods modify the private data in a
manner that is according to how the class should work. There are usually ways
to achieve this in the programming language without breaking the encapsulation
principle totally.
In C# it is possible to mark components as public, protected,
private, and internal. protected components of an
object are only available for inheritance while private components are only available to
the object which they have been declared in. Components of an object that are
declared as internal are only available within the software module, however it
is possible to allow other modules access to them by adding an attribute to the
AssemblyInfo.cs file.
For example if we have a class named AClass that has internal members and we want to have
access to them in the unit test project called AClassUnitTest
the following line should be added to the AssemblyInfo.cs
file which houses the AClass
file:
[assembly: InternalsVisibleTo("AClassUnitTest")]
Declaring an internal constructor which allows for injecting
mocks into the class that should be tested is good usage of this functionality.
The private and protected components can also be accessed through what is
called Accessors. There is an article on MSDN on using Accessors on MSDN
In C++ there is the friend
keyword that can be used to access private components of another object.
1: #include <iostream>
2: using namespace std;
3: // Predeclaration for AClass so the BClass is aware of it existance.
4: class AClass;
5: class BClass {
6: private:
7: int data;
8: void printData() { cout << data << endl; }
9: public:
10: BClass (int insertData) : data(insertData) {}
11: friend AClass;
12: };
13: class AClass {
14: private:
15: BClass* dataClass;
16: public:
17: AClass (BClass *insertDataClass) : dataClass(insertDataClass) {}
18: virtual ~AClass() { delete dataClass; }
19: void fireDataClass() {
20: if (dataClass)
21: dataClass->printData(); // Calling the private method on BClass
22: }
23: };
24: int main(int argc, char* argv[]) {
25: AClass friendClass(new BClass(10));
26: friendClass.fireDataClass();
27: return 0;
28: }
In the example above the AClass
can access both the private
function and data of the BClass which is due to that the BClass friends AClass on row 11. Simply by pre-declaring a unit test
class it is possible to prepare a class so that the internal members are
available for unit testing. A more in depth description of the friend keyword and its usage can be
found here
However testing private data with unit test makes the black
box, that objects usually are, transparent. Changing the internal functionality
of the objet will then carry a high probability of breaking the unit test even
though the functional contract of the object has not been violated. There are
good grounds to treat objects as black boxes even during the testing of the
objects.
Unit test should only verify the externally visible components
of an object so it is possible to safely refactor the code of the object
without destroying its usability. Rewriting of a test should only occur when
the object has had a breaking change to its interface and this should indeed be
a time for reflection on what has been done.
Why not apply the commando pattern?
ReplyDeletehttp://www.javaperformancetuning.com/articles/commando.shtml
This seems like a good way in java to achieve access to private and protected variables however this does not change my position that the parts of the object should not be tested.
DeleteEven though unit test are meant to be rapid I don't believe that any extra performance enhancements should be added to create unit tests.
This pattern also seems to carry the burden that it has a break point where it gets usable, that is when the benefit of removing method calls is outweigh the cost of reflection. This cost is certainly not the same between different programming languages so I think there should be some measurements when applying it.
Thanks for the link, it was a very interesting read.
Bah! Should perhaps have read the final part of the article that explains that it's a joke. Good one.
DeleteOT
ReplyDeleteEven if it is a joke and it's definitely not usable for unit testing, many very widespread libraries/frameworks like spring and hibernate make use of reflection to get their work done. This might become evident only when you realise that your code coverage never hits accessor/property methods on entity objects and proxied spring beans.
This is mostly a result of java having been with us for a longer time letting developers find the quirks around the language and into the VM. Results are seen in high performance open source utility libraries in one end and the new era of languages running on the JVM in the other.
The commando pattern lets the strict and nowadays code heavy Java keep its place as a first class citizen. It simply opens up the possibilities in the otherwise limited language to give it capabilities of the looser and more flexible ones.
You can probably find more patterns behind the link below that might seem like jokes, but are actually in use and making sense.
http://www.lsd.ic.unicamp.br/~oliva/fun/prog/resign-patterns
Oh, and there are many that are used, and makes no sense at all.