From d26f774ae1e00e789c6793034367b21e5a125804 Mon Sep 17 00:00:00 2001 From: Jason Duffy Smith Date: Mon, 25 Aug 2014 11:59:15 +1000 Subject: [PATCH 1/2] Added the type and method name to error messages reported for missing method mocks --- Delphi.Mocks.MethodData.pas | 51 ++++++++++++++++++++----------------- Delphi.Mocks.Proxy.pas | 5 +++- Delphi.Mocks.pas | 9 ++++++- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/Delphi.Mocks.MethodData.pas b/Delphi.Mocks.MethodData.pas index 0c2e93a..c0d2194 100644 --- a/Delphi.Mocks.MethodData.pas +++ b/Delphi.Mocks.MethodData.pas @@ -40,6 +40,7 @@ interface type TMethodData = class(TInterfacedObject,IMethodData) private + FTypeName : string; FMethodName : string; FBehaviors : TList; FReturnDefault : TValue; @@ -87,7 +88,7 @@ TMethodData = class(TInterfacedObject,IMethodData) function Verify(var report : string) : boolean; public - constructor Create(const AMethodName : string; const AIsStub : boolean); + constructor Create(const ATypeName : string; const AMethodName : string; const AIsStub : boolean); destructor Destroy;override; end; @@ -107,8 +108,9 @@ implementation { TMethodData } -constructor TMethodData.Create(const AMethodName : string; const AIsStub : boolean); +constructor TMethodData.Create(const ATypeName : string; const AMethodName : string; const AIsStub : boolean); begin + FTypeName := ATypeName; FMethodName := AMethodName; FBehaviors := TList.Create; FExpectations := TList.Create; @@ -129,7 +131,7 @@ procedure TMethodData.Exactly(const times: Cardinal); begin expectation := FindExpectation([TExpectationType.Exactly,TExpectationType.ExactlyWhen]); if expectation <> nil then - raise EMockException.Create('Expectation Exactly already defined on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Exactly for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateExactly(FMethodName,times); FExpectations.Add(expectation); end; @@ -141,7 +143,7 @@ procedure TMethodData.ExactlyWhen(const times: Cardinal; begin expectation := FindExpectation(TExpectationType.ExactlyWhen,Args); if expectation <> nil then - raise EMockException.Create('Expectation Exactly already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Exactly for method [%s] with args.', [FTypeName, FMethodName])); expectation := TExpectation.CreateExactlyWhen(FMethodName,times,Args); FExpectations.Add(expectation); end; @@ -257,7 +259,7 @@ procedure TMethodData.AtLeast(const times: Cardinal); begin expectation := FindExpectation([TExpectationType.AtLeast,TExpectationType.AtLeastOnce,TExpectationType.AtLeastOnceWhen,TExpectationType.AtLeastWhen]); if expectation <> nil then - raise EMockException.Create('Expectation At Least already defined on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation At Least for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateAtLeast(FMethodName,times); FExpectations.Add(expectation); end; @@ -268,7 +270,7 @@ procedure TMethodData.AtLeastOnce; begin expectation := FindExpectation([TExpectationType.AtLeast,TExpectationType.AtLeastOnce,TExpectationType.AtLeastOnceWhen,TExpectationType.AtLeastWhen]); if expectation <> nil then - raise EMockException.Create('Expectation At Least already defined on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation At Least Once for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateAtLeastOnce(FMethodName); FExpectations.Add(expectation); end; @@ -279,7 +281,7 @@ procedure TMethodData.AtLeastOnceWhen(const Args: TArray); begin expectation := FindExpectation(TExpectationType.AtLeastOnceWhen,Args); if expectation <> nil then - raise EMockException.Create('Expectation At Least Once already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation At Least Once When for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateAtLeastOnceWhen(FMethodName,Args); FExpectations.Add(expectation); end; @@ -290,7 +292,7 @@ procedure TMethodData.AtLeastWhen(const times: Cardinal; const Args: TArray nil then - raise EMockException.Create('Expectation At Least already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation At Least When for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateAtLeastWhen(FMethodName,times,Args); FExpectations.Add(expectation); end; @@ -301,7 +303,7 @@ procedure TMethodData.AtMost(const times: Cardinal); begin expectation := FindExpectation([TExpectationType.AtMost,TExpectationType.AtMostWhen]); if expectation <> nil then - raise EMockException.Create('Expectation At Most already defined on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation At Most for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateAtMost(FMethodName,times); FExpectations.Add(expectation); end; @@ -313,7 +315,7 @@ procedure TMethodData.AtMostWhen(const times: Cardinal; begin expectation := FindExpectation(TExpectationType.AtMostWhen,Args); if expectation <> nil then - raise EMockException.Create('Expectation At Most already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation At Most When for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateAtMostWhen(FMethodName,times,Args); FExpectations.Add(expectation); end; @@ -334,7 +336,7 @@ procedure TMethodData.Between(const a, b: Cardinal); begin expectation := FindExpectation([TExpectationType.Between,TExpectationType.BetweenWhen]); if expectation <> nil then - raise EMockException.Create('Expectation Between already defined on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Between for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateBetween(FMethodName,a,b); FExpectations.Add(expectation); end; @@ -345,7 +347,7 @@ procedure TMethodData.BetweenWhen(const a, b: Cardinal;const Args: TArray nil then - raise EMockException.Create('Expectation Between already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Between When for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateBetweenWhen(FMethodName,a,b,Args); FExpectations.Add(expectation); end; @@ -358,8 +360,8 @@ procedure TMethodData.Never; begin expectation := FindExpectation([TExpectationType.Never ,TExpectationType.NeverWhen]); if expectation <> nil then - raise EMockException.Create('Expectation Never already defined on method : ' + FMethodName); - + raise EMockException.Create(Format('[%s] already defines Expectation Never for method [%s]', [FTypeName, FMethodName])); + expectation := TExpectation.CreateNever(FMethodName); FExpectations.Add(expectation); end; @@ -370,7 +372,7 @@ procedure TMethodData.NeverWhen(const Args: TArray); begin expectation := FindExpectation(TExpectationType.NeverWhen,Args); if expectation <> nil then - raise EMockException.Create('Expectation Never already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Never When for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateNeverWhen(FMethodName,Args); FExpectations.Add(expectation); end; @@ -381,7 +383,7 @@ procedure TMethodData.Once; begin expectation := FindExpectation([TExpectationType.Once,TExpectationType.OnceWhen]); if expectation <> nil then - raise EMockException.Create('Expectation Once already defined on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Once for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateOnce(FMethodName); FExpectations.Add(expectation); end; @@ -392,7 +394,7 @@ procedure TMethodData.OnceWhen(const Args: TArray); begin expectation := FindExpectation(TExpectationType.OnceWhen,Args); if expectation <> nil then - raise EMockException.Create('Expectation Once already defined for these args on method : ' + FMethodName); + raise EMockException.Create(Format('[%s] already defines Expectation Once When for method [%s]', [FTypeName, FMethodName])); expectation := TExpectation.CreateOnceWhen(FMethodName,Args); FExpectations.Add(expectation); end; @@ -419,7 +421,8 @@ procedure TMethodData.RecordHit(const Args: TArray; const returnType : T if FIsStub then result := GetDefaultValue(returnType) else - raise EMockException.Create('No default return value defined for method ' + FMethodName); + raise EMockException.Create(Format('[%s] has no default return value defined for method [%s]', [FTypeName, FMethodName])); + returnVal := FReturnDefault; end; if returnType <> nil then @@ -456,7 +459,7 @@ procedure TMethodData.WillExecute(const func: TExecuteFunc); begin behavior := FindBehavior(TBehaviorType.WillExecute); if behavior <> nil then - raise EMockSetupException.Create('WillExecute already defined for ' + FMethodName ); + raise EMockSetupException.Create(Format('[%s] already defines WillExecute for method [%s]', [FTypeName, FMethodName])); behavior := TBehavior.CreateWillExecute(func); FBehaviors.Add(behavior); end; @@ -467,7 +470,7 @@ procedure TMethodData.WillExecuteWhen(const func: TExecuteFunc;const Args: TArra begin behavior := FindBehavior(TBehaviorType.WillExecuteWhen,Args); if behavior <> nil then - raise EMockSetupException.Create('WillExecute.When already defined with these parameters for method ' + FMethodName ); + raise EMockSetupException.Create(Format('[%s] already defines WillExecute When for method [%s]', [FTypeName, FMethodName])); behavior := TBehavior.CreateWillExecuteWhen(Args, func); FBehaviors.Add(behavior); end; @@ -478,7 +481,7 @@ procedure TMethodData.WillRaiseAlways(const exceptionClass: ExceptClass; const m begin behavior := FindBehavior(TBehaviorType.WillRaiseAlways); if behavior <> nil then - raise EMockSetupException.Create('WillRaise already defined for method ' + FMethodName ); + raise EMockSetupException.Create(Format('[%s] already defines Will Raise Always for method [%s]', [FTypeName, FMethodName])); behavior := TBehavior.CreateWillRaise(exceptionClass,message); FBehaviors.Add(behavior); end; @@ -489,7 +492,7 @@ procedure TMethodData.WillRaiseWhen(const exceptionClass: ExceptClass; const mes begin behavior := FindBehavior(TBehaviorType.WillRaise,Args); if behavior <> nil then - raise EMockSetupException.Create('WillRaise.When already defined for method ' + FMethodName ); + raise EMockSetupException.Create(Format('[%s] already defines Will Raise When for method [%s]', [FTypeName, FMethodName])); behavior := TBehavior.CreateWillRaiseWhen(Args,exceptionClass,message); FBehaviors.Add(behavior); end; @@ -497,7 +500,7 @@ procedure TMethodData.WillRaiseWhen(const exceptionClass: ExceptClass; const mes procedure TMethodData.WillReturnDefault(const returnValue: TValue); begin if not FReturnDefault.IsEmpty then - raise EMockSetupException.Create('Default return Value already specified for ' + FMethodName); + raise EMockSetupException.Create(Format('[%s] already defines Will Return Default for method [%s]', [FTypeName, FMethodName])); FReturnDefault := returnValue; end; @@ -507,7 +510,7 @@ procedure TMethodData.WillReturnWhen(const Args: TArray; const returnVal begin behavior := FindBehavior(TBehaviorType.WillReturn,Args); if behavior <> nil then - raise EMockSetupException.Create('WillReturn.When already defined with these parameters for method ' + FMethodName ); + raise EMockSetupException.Create(Format('[%s] already defines Will Return When for method [%s]', [FTypeName, FMethodName])); behavior := TBehavior.CreateWillReturnWhen(Args,returnValue); FBehaviors.Add(behavior); end; diff --git a/Delphi.Mocks.Proxy.pas b/Delphi.Mocks.Proxy.pas index 5b25214..2fc8a33 100644 --- a/Delphi.Mocks.Proxy.pas +++ b/Delphi.Mocks.Proxy.pas @@ -475,12 +475,15 @@ function TProxy.GetBehaviorMustBeDefined: boolean; function TProxy.GetMethodData(const AMethodName: string): IMethodData; var methodName : string; + pInfo : PTypeInfo; begin methodName := LowerCase(AMethodName); if FMethodData.TryGetValue(methodName,Result) then exit; - Result := TMethodData.Create(AMethodName,FIsStubOnly); + pInfo := TypeInfo(T); + + Result := TMethodData.Create(pInfo.Name, AMethodName, FIsStubOnly); FMethodData.Add(methodName,Result); end; diff --git a/Delphi.Mocks.pas b/Delphi.Mocks.pas index a4b2f67..1481830 100644 --- a/Delphi.Mocks.pas +++ b/Delphi.Mocks.pas @@ -107,7 +107,6 @@ interface //If true, calls to methods for which we have not defined a behavior will cause verify to fail. property BehaviorMustBeDefined : boolean read GetBehaviorMustBeDefined write SetBehaviorMustBeDefined; - end; //We use the Setup to configure our expected behaviour rules and to verify @@ -272,7 +271,15 @@ procedure TMock.Implement; end; function TMock.Instance : T; +var + pInfo : PTypeInfo; begin + if FProxy = nil then + begin + pInfo := TypeInfo(T); + raise EMockException.Create(format('Mock [%s] did not have create called before its use.', [pInfo.Name])); + end; + result := FProxy.Proxy; end; From 814f60cb7905204ca764d5fbb2504e7a22db5f8a Mon Sep 17 00:00:00 2001 From: Jason Duffy Smith Date: Mon, 25 Aug 2014 12:08:54 +1000 Subject: [PATCH 2/2] Fixed TMethodData.RecordHit exception raising. There was a else clause that would never be hit. --- Delphi.Mocks.MethodData.pas | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Delphi.Mocks.MethodData.pas b/Delphi.Mocks.MethodData.pas index f53ce3f..f371851 100644 --- a/Delphi.Mocks.MethodData.pas +++ b/Delphi.Mocks.MethodData.pas @@ -427,11 +427,9 @@ procedure TMethodData.RecordHit(const Args: TArray; const returnType : T if (returnType <> nil) and (FReturnDefault.IsEmpty) then if FIsStub then result := GetDefaultValue(returnType) - else - raise EMockException.Create(Format('[%s] has no default return value defined for method [%s]', [FTypeName, FMethodName])); - else if FBehaviorMustBeDefined and (expectationHitCtr = 0) and (FReturnDefault.IsEmpty) then - raise EMockException.Create(Format('[%s] has no behaviour or expectation defined for method [%s]', [FTypeName, FMethodName])); - + else if FBehaviorMustBeDefined and (expectationHitCtr = 0) and (FReturnDefault.IsEmpty) then + raise EMockException.Create(Format('[%s] has no behaviour or expectation defined for method [%s]', [FTypeName, FMethodName])); + returnVal := FReturnDefault; end; if returnType <> nil then