3

I have to unit tests some forms in Delphi. My boss wants me to write tests to check if events are assigned. There are so many that we have to run some checks on them.

For example, I want to check that

TMyForm.OnCreate = TMyForm.FormCreate.

To do this, I wrote :

function TFMaitreTest.SameMethod(const Method1, Method2: TNotifyEvent; msg : string = ''): boolean;
begin
Assert.IsTrue(TEqualityComparer<TNotifyEvent>.Default.Equals(Method1, Method2), msg);
end;

But using this way, I have to override the SameMethod for every kind of event delegate : TNotifyEvent, TDataSetEvent, ...

I then thought of using generics, as such :

function TFMaitreTest.SameMethod<T>(const Method1, Method2: T; msg : string = ''): boolean;

But this does not compile. TEqualityComparer needs some Generic constraint, but a generic constraint cannot be defined for a procedure of object. Using TMethod as a constraint does not work either. Maybe there's a way here, but I have not found it.

Then, I thought of changing approach altogether using Rtti. I want to compare the methods using Rtti, but for that, I have to know the name of the method with a string.

RttiType.GetMethod(methodName)

Here, methodName is a pure string. If we refactor and methodName becomes MyMethod, we're kind of screwed and have to check manually everywhere this string is used. We would like to have compile time errors. It's less error prone.

C# has the concept of lambda expressions which is very powerful for these kind of scenarios :

See Get the name of a method using an expression

How can I write a more generic way of testing if an event property is assigned to a specific procedure, without having to write a method for every event kind ?

Thank you for your help.

Community
  • 1
  • 1
Ludovic C
  • 2,855
  • 20
  • 40
  • I am assuming that you are using DUnitX because I spotted the use of `Assert.IsTrue`. So doesn't `Assert.AreEqual` do what you want? – Stefan Glienke Feb 03 '16 at 15:22
  • @StefanGlienke Completely overlooked that simple solution. I tested it quickly and I think it does the trick. Please write this as an answer so I can accept it. – Ludovic C Feb 03 '16 at 15:25

1 Answers1

6

Since you are using the DUnitX Assert type you should use its AreEqual<T> method which does exactly what you want - you have to specify the generic type parameter though and cannot let the compiler infer it:

Assert.AreEqual<TNotifyEvent>(myForm.OnCreate, myForm.FormCreate);
Stefan Glienke
  • 20,860
  • 2
  • 48
  • 102
  • 1
    An alternative, without having to use Generics, would be to use RTTI to retrieve the current value assigned to the object's event, then if that value is assigned to a method (type-cast the value to `TMethod` and check if its `Code` field is not nil), then use RTTI to retrieve the method's name and check if that is the same name as your desired method, and also check if the `TMethod.Data` field is pointing at the desired object. – Remy Lebeau Feb 04 '16 at 06:04