1

これで髪を抜いています。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()を呼び出し、次にIsValidAccount()を呼び出すため、サービスで内部呼び出しが発生しています。

おそらく解決策は、長くて複雑なMapAccountFromXml()およびIsValidAccount()コードを分割して、GetAccount()呼び出しにインラインで配置することを心配することではありませんが、コードを読みやすくするために、それらを分割したままにしておきます。

Molesアセンブリを作成しましたが、このようなクラスのスタブバージョンを作成できることを知っています

var stubWebService = SIExternalWebServiceProxy {
       GetAllCustomerAccounts = delegate {
            return SomeHelper.GetFakeXmlDocument();
       }
}

var stubAccountService = new SAccountService() { callsBase = true; }

私の問題は、MapAccountFromXmlとIsValidAccountへの内部呼び出しをオーバーライドする方法がわからないことです。また、単体テストでこれらのメソッドをテストしたくないので、テスト用にGetAccountsを分離したいと思います。部分的なスタブでオーバーライドするには仮想である必要があるメソッドをどこかで読みましたが、テストするメソッドのベースを呼び出しているときに、いくつかのメソッドをオーバーライドするスタブを作成する方法を示すものは見つかりませんでした。

4

2 に答える 2

1

ピアは私を正しい軌道に乗せてくれました、ありがとう。

私が探していたのは、MolesのDetoursと呼ばれていることがわかりました。を使用してインターフェイスをスタブするのではなく

var stubAccountService = new SIAccountService();

私がする必要があったのは、AccountServiceのインスタンスを作成してから、このようにモックしたいメソッドへのすべての呼び出しを迂回することでした。

var accountService = new AccountService();

MAccountService.AllInstances.MapAccountFromXmlXmlNode = delegate { 
    return new AccountModel(); 
};

MAccountServiceは、アセンブリをMoleするときにMolesによって提供されます。これに欠けている唯一の部分は、これが機能するためには、テストメソッドに次の属性を追加する必要があるということです。

[HostType("Moles")]

これはローカルでは機能しましたが、最終的にTFSに自動ビルドを実行させるのに問題がありました

アップデート

Rhino Mocksを見ながら、これを行う別の方法に出くわしました。モックされているクラスのメソッドが仮想である場合は、次のようにモックでメソッドをオーバーライドできます。

var accountService = new SAccountService();
accountService.MapAccountFromXmlXmlNode = delegate
    {
        return new AccountModel();
    }

今、私は呼び出すことができます

accountService.GetMemberAccounts();

accountServiceがMapAccountFromXmlを呼び出すと、スタブによってキャッチされ、必要に応じて処理されます。HostTypeをいじることはなく、魅力のように機能します。

于 2012-10-24T16:03:40.120 に答える
0

issolationでクラスのメソッドをテストするには、IsValidAccountメソッドとMapAccountFromXmlメソッドのmolを作成することにより、molを使用してこれを行います。または、baseを使用してスタブが元のメソッドを呼び出せるようにするスタブを使用してスタブ実装を作成します。または、より良い解決策だと思うので、スタブしたいメソッドをオーバーライドするテストクラスを作成します(これは、自分のコードで何が起こっているかをすべて確認できることを除いて、スタブが行うことと同じです)。

public class TestHelperAccountService : AccountService {

    public override AccountModel MapAccountFromXml(XmlNode node) {
        return new AccountModel(){
                    //Accountmodelstub
              };
    {

    public override bool IsValidAccount(XmlNode node) 
    {
        return true;
    }
}

このようにして、GetAccountメソッドが完全な分離で実行されるTestHelperAccountServiceクラスでGetAccountメソッドのテストを実行できます。MapAccountFromXmlのようなメソッドについても同じことを実行して、それらを個別にテストできます。

于 2012-10-11T08:32:36.223 に答える