I am trying to fake a call to a parents public virtual validate method from the child without success (using FakeItEasy
. I have a base class that validates simple commands for similar command classes (I have reduced the code for simplicity sake):
public class CanSetSettings<TSettings> : IValidationhandler<TSettings> where TSettings : ISetting
{
protected readonly IFooRepository Repository;
protected List<ValidationResult> Results;
public CanSetSettings(IFooRepository repository)
{
if (Repository== null)
throw new ArgumentNullException("IFooRepository ", "IFooRepository is needed to validate the command.");
repository = repository;
Results = new List<ValidationResult>();
}
public virtual ICollection<ValidationResult> Validate(TSettings settings)
{
if (settings == null)
{
Results.Add(new ValidationResult("Settings", "The command to validate cannot be missing."));
return Results;
}
if (Repository.Query(settings.Location) == null)
Results.Add(new ValidationResult("Location", "No Location was found for your settings."));
return Results;
}
Then I have child classes that inherits from this base class and then implements their specific logic by overriding Validate
(simplified my code).
public class CanSetSpecificSetting : CanSetSettings<SetSpecificSettings>, IValidationhandler<SetSpecificSettings>
{
public CanSetSpecificSetting (IFooRepository repo)
: base(repo)
{ }
public override ICollection<ValidationResult> Validate(SetSpecificSettings command)
{
base.Validate(command); // TODO determine if this call was made
// ... other logic here
return results;
}
}
I have tried this in my unit test and it only configures the method call to the child class and I cannot configure the parent. How do I configure the fake to call the child class and fake the parent base class method? Thank you.
var _repository = A.Fake<IFooRepository>();
var _validator = A.Fake<CanSetSpecificSetting>(opt => opt.WithArgumentsForConstructor(new object[] { _repository }));
A.CallTo(() => _validator.Validate(_cmd)).CallsBaseMethod().Once();
_validator.Validate(_cmd);
// this passes, but only because it knows about the child call
A.CallTo(() => _validator.Validate(_cmd)).MustHaveHappened(Repeated.Exactly.Once);
No, I don't think you can easily do what you intend to do using FakeItEasy. I don't even think you should do that.
BUT you can achieve something similar, by encapsulating the base call into a template method in your subclass. Just change
CanSetSpecificSetting
, like this:And then change your test like this:
Again, this is ugly. The only case I can imagine that doing this would be ok is adding tests to some legacy code that you intend (and will) refactor as soon as possible.
Hope it helps.