Mapping columns to properties becomes quite
cumbersome with more complex objects.
In real-life projects, domain packages
probably already have a good
data-transfer object
(DTO), so
this direct mapping just complicates test classes unnecessarily.
FitNesse allows us to use a data-transfer object directly
without declaring all its properties in a fixture class. In order
to do that, we override the
GetTargetObject
method of the
Fixture class to specify our DTO.
In this case, we use the
PlayerRegistrationInfo
class,[15]
which implements the IPlayerRegistration data-transfer interface.
When GetTargetObject is overriden,
the fixture class
tells FitNesse how to execute tests, but does not
directly provide the test implementation. For example, our fixture
can just tell FitNesse to execute a
ColumnFixture test, but the target object
has to implement properties and methods for table columns.
When a target object is provided, all table columns must be bound to this
object. You cannot mix and match — the whole table is mapped either
to the fixture or to the target object. This includes test methods
and additional setup columns, which do not exist in the DTO
object. I typically solve this by creating an inner class in the fixture that
extends the
DTO class with test methods.
Tristan/test/PlayerRegistration.cs
68 public class PlayerRegisters : ColumnFixture
69 {
70 public class ExtendedPlayerRegistrationInfo: PlayerRegistrationInfo
71 {
72 public int PlayerId()
73 {
74 return SetUpTestEnvironment.playerManager.RegisterPlayer(this);
75 }
76 }
77 private ExtendedPlayerRegistrationInfo to =
78 new ExtendedPlayerRegistrationInfo();
79 public override object GetTargetObject()
80 {
81 return to;
82 }
83 }
We can use this technique to fill in all the
PlayerRegistrationInfo
properties without redeclaring them in fixture code, and
then use a ready-made DTO as an input for test methods.
We can use a similar approach for binding
DTO properties to columns that
contain expected test results.
Theoretically, we could use the same table row to store
the player ID and read other properties into the
DTO, but this would require copying
values from one
DTO
object to another. The target object can be switched at run time,
which is a good way to solve this problem in Java,
but because C# inner classes do not have access to
outer class instances, this would not be a clean solution.
It is much better to use a fixture argument (see
Replace repetitive values with arguments) to
load the DTO. Sometimes
it is quite convenient to use a FitNesse symbol value as
the argument, as in this case, because the new player ID is already in a symbol.
However, symbols cannot be directly used as arguments.[16]
We can pass the symbol name as an
argument and read it in the test class, using
Fixture.Recall(symbolName). Note that you should not use
>> or << in this case, just the plain symbol name.
Tristan/test/PlayerRegistration.cs
84 public class CheckStoredDetailsFor : ColumnFixture
85 {
86 public override object GetTargetObject()
87 {
88 int newid=(int)Fixture.Recall(Args[0]);
89 return SetUpTestEnvironment.playerManager.GetPlayer(newid);
90 }
91 }



