我用这个把头发拉出来。我已经查看并找不到使用 Microsoft Moles 创建和使用部分存根的简单、清晰的示例。也许我错过了一些东西,或者我的代码架构很差,但我似乎无法让它工作。
这是我的课(简化版):
public class AccountService : IAccountService {
private readonly webServiceProxy IExternalWebServiceProxy;
public AccountService(IExternalWebServiceProxy webServiceProxy) {
this.webServiceProxy = webServiceProxy;
}
public List<AccountModel> GetAccounts(string customerId) {
var returnList = new List<AccountModel>();
var xmlResponse = webServiceProxy.GetAllCustomerAccounts(customerId);
var accountNodes = xmlResponse.SelectNodes("//AccountNodes");
if (accountNodes != null)
{
foreach (XmlNode node in accountNodes)
{
var account = this.MapAccountFromXml(node);
if (!string.IsNullOrEmpty(account.AccountNumber))
{
returnList.Add(account);
}
}
}
return returnList;
}
public AccountModel MapAccountFromXml(XmlNode node) {
if (!IsValidAccount(node) {
return null;
}
// This performs a lot of XML manipulation getting nodes based on attributes
// and mapping them to the various properties of the AccountModel. It's messy
// and I didn't want it inline with the other code.
return populatedAccountModel;
{
public bool IsValidAccount(XmlNode node)
{
var taxSelectValue = node.SelectSingleNode("//FORMAT/Field[@taxSelect='1']").First().Value;
var accountStatus = // similar to first line in that it gets a single node using a specific XPath
var maturityDate = // similar to first line in that it gets a single node using a specific XPath
var maturityValue = // similar to first line in that it gets a single node using a specific XPath
return taxSelectValue != string.Empty && taxSelectValue != "0" && (accountStatusValue != "CL" || (maturityDate.Year >= DateTime.Now.AddYears(-1).Year));
}
}
我想做的是测试我的 GetAccounts() 方法。我可以存根 IExternalWebServiceProxy 调用并返回假 XML,但我的服务中发生了内部调用,因为我的 GetAccounts() 方法调用 MapAccountFromXml(),而 MapAccountFromXml() 又调用 IsValidAccount()。
也许解决方案是不用担心分解冗长且涉及的 MapAccountFromXml() 和 IsValidAccount() 代码,只需将它们内联到 GetAccount() 调用中,但我宁愿将它们分解为代码可读性。
我创建了我的 Moles 程序集,并且知道我可以像这样创建我的类的存根版本
var stubWebService = SIExternalWebServiceProxy {
GetAllCustomerAccounts = delegate {
return SomeHelper.GetFakeXmlDocument();
}
}
var stubAccountService = new SAccountService() { callsBase = true; }
我的问题是我不知道如何覆盖对 MapAccountFromXml 和 IsValidAccount 的内部调用,并且我不希望我的单元测试测试这些方法,我想隔离 GetAccounts 进行测试。我在某处读到方法需要是虚拟的才能在部分存根中被覆盖,但是找不到任何东西来说明如何创建一个覆盖几个方法的存根,同时为我想要测试的方法调用基。