gpt4 book ai didi

c# - FakeItEasy,从子类伪造一个父虚方法

转载 作者:行者123 更新时间:2023-11-30 16:09:29 26 4
gpt4 key购买 nike

我试图从 child 那里伪造对 parent 公共(public)虚拟验证方法的调用但没有成功(使用 FakeItEasy。我有一个基类可以验证类似命令类的简单命令(我减少了为简单起见的代码):

  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;
}

然后我有继承自这个基类的子类,然后通过覆盖Validate(简化我的代码)来实现它们的特定逻辑。

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;
}
}

我已经在我的单元测试中试过了,它只配置了对子类的方法调用,我无法配置父类。如何配置伪调用子类并伪造父基类方法?谢谢。

      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);

最佳答案

不,我不认为您可以使用 FakeItEasy 轻松地完成您想要做的事情。我什至认为你不应该那样做。

但是您可以通过将基调用封装到子类中的模板方法中来实现类似的效果。只需更改 CanSetSpecificSetting,如下所示:

public class CanSetSpecificSetting : CanSetSettings<SetSpecificSettings>, IValidationhandler<SetSpecificSettings>
{
public CanSetSpecificSetting (IFooRepository repo)
: base(repo)
{ }

public override ICollection<ValidationResult> Validate(SetSpecificSettings command)
{
BaseValidate(command); // << Instead of calling base.Validate(command).

// ... other logic here

return results;
}

// This is the template method. You MUST declare it as virtual.
protected virtual ICollection<ValidationResult> BaseValidate(SetSpecificSettings command)
{
return base.Validate(command);
}
}

然后像这样改变你的测试:

var _repository = A.Fake<IFooRepository>();
var _validator = A.Fake<CanSetSpecificSetting>(opt => opt.WithArgumentsForConstructor(new object[] { _repository }));

A.CallTo(() => _validator.Validate(_cmd)).CallsBaseMethod().Once();

// *** ADD THIS LINE *** must configure it this way because the template method is protected - we don't want to make it public!
A.CallTo(_validator).WhereMethod(x => x.Name == "BaseValidate").Returns("whatever-you-want-to-return");

_validator.Validate(_cmd);

A.CallTo(() => _validator.Validate(_cmd)).MustHaveHappened(Repeated.Exactly.Once);

同样,这很丑陋。我能想到的唯一可以这样做的情况是向您打算(并将)尽快重构的一些遗留代码添加测试。

希望对您有所帮助。

关于c# - FakeItEasy,从子类伪造一个父虚方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27573520/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com