0

I'm using mocking technique in DUnitX project for ShowMessage dialog.Because I don't want that ShowMessage stops test execution. I tried with this but it is not working.

unit TestMain2;

interface

uses
  DUnitX.TestFramework, Main, Vcl.Dialogs, System.SysUtils, Windows, Vcl.Forms, Winapi.Messages;

type
  TMockShowMessageHelper = class
  private
    class var FAutoProceed: Boolean;
    class var FCapturedMessage: string;
    class procedure MockShowMessage(const Msg: string);
  public
    class property AutoProceed: Boolean read FAutoProceed write FAutoProceed;
    class property CapturedMessage: string read FCapturedMessage;
  end;

  [TestFixture]
  TMyTestObject = class
  private
    procedure SimulateButtonClick;
  public
    [Setup]
    procedure Setup;
    [TearDown]
    procedure TearDown;
    [Test]
    procedure Test1;
  end;

implementation

// Mock implementation of ShowMessage
class procedure TMockShowMessageHelper.MockShowMessage(const Msg: string);
begin
  FCapturedMessage := Msg;
  if FAutoProceed then
    PostMessage(Application.Handle, WM_CLOSE, 0, 0);
end;

var
  MainFormT: TMainForm;

procedure TMyTestObject.Setup;
begin
  MainFormT := TMainForm.Create(nil);
  // Replace ShowMessage with our mock implementation
  Vcl.Dialogs.ShowMessage := TMockShowMessageHelper.MockShowMessage;
end;

procedure TMyTestObject.TearDown;
begin
  MainFormT.Free;
end;

procedure TMyTestObject.SimulateButtonClick;
begin
  MainFormT.Button1.Click;
end;

procedure TMyTestObject.Test1;
begin
  TMockShowMessageHelper.AutoProceed := True; // Set this flag to automatically proceed
  SimulateButtonClick;
end;

initialization
  TMockShowMessageHelper.AutoProceed := False; // Set the flag to default value
  TDUnitX.RegisterTestFixture(TMyTestObject);

end.

Compiler error:

E2250 There is no overloaded version of 'ShowMessage' that can be called with these arguments

How to fix this? Or is there any better way to do the same? Changing orginal unit that I'm testing is not an option.

I need to do similar for MessageDlg.

Ivan
  • 85
  • 6
  • 3
    If _changing the original unit is not an option_ - well, you are probably running out of options pretty soon. – Uwe Raabe Jul 22 '23 at 08:45
  • 1
    The compiler tells you that in that context you may only **call** a procedure/function instead of treating is like a variable (which it isn't) to **assign** a new value. Wherever you did that before you used **variables** (which could then be also **called** like functions). Your code essentially is: `OldFunction:= NewFunction` and the compiler complains that `OldFunction` without any parameter doesn't exist - would it exist, it would further complain that the left side cannot be assigned to. Don't confuse that with `OnEvent` handlers, which are **variables**. – AmigoJack Jul 22 '23 at 13:12
  • 1
    Unit testing is an automating testing therefore it is expected that it can work without any user input. Now dialog on the other hand are designed for receiving user input and in case of modal dialog even halting the code flow in order to wait for user input. So I would recommend that you create a new custom unit `SimulatedDialogs` which contains several methods and if needed classes that will mimic working of standard dialogs and even simulate user input where needed. And then all you do is replace `VCL.Dialogs` un uses section with your `SimulatedDialogs` unit. – SilverWarior Jul 22 '23 at 13:32

0 Answers0