Chr☆s Kwok 的技术笔记

.NET, C#, WPF, WCF, WF, .NetCore & LINQ ... I know how it works because I know why it works ...

博客园 首页 新随笔 订阅 管理

通常单元测试需要访问受测类的私有方法或属性,一般需要使用VSTS自动生成的访问器,但是对于该类的父类私有属性就无法访问了,这也是上一篇博文提到的状况。其实我们还可以自己编写访问器,这样就不需要受到系统生成的访问器的束缚(由于生成的访问器没有源码无法修改)。下文就是一个范例(受测项目BankDemo.csproj,程序集BankDemo.exe):

========受测类的实现代码:========

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BankDemo
{
    
public class BankAccount
    {
        
private int _accountNo;
        
private float _currentBalance;
        
private static float _bankAsset;
        
private static int _newUniqueAccountNo;

        
private static int GetUniqueAccountNo
        {
            
get { return ++_newUniqueAccountNo; }
        }

        
private float CurrentBalance
        {
            
get { return _currentBalance; }
            
set { _currentBalance = value; }
        }

        
// Constructors for new account
        private BankAccount(float initialBalance)
        {
            
this._accountNo = GetUniqueAccountNo;
            
this._currentBalance = initialBalance;
            _bankAsset 
+= initialBalance;
        }

        
// Methods
        private float DepositMoney(float depositAmount)
        {
            
this.CurrentBalance += depositAmount;
            _bankAsset 
+= depositAmount;
            
return this.CurrentBalance;
        }

        
private float WithdrawMoney(float withdrawAmount)
        {
            
this.CurrentBalance -= withdrawAmount;
            _bankAsset 
-= withdrawAmount;
            
return this.CurrentBalance;
        }

        
private static float BankAsset()
        {
            
return _bankAsset;
        }

    }


}

 

========访问器代码可以这样实现:========  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;


namespace TestProject1
{
    
class BankAccountAccessor
    {
        PrivateObject _privateObject;
        
static PrivateType _privateType = new PrivateType("BankDemo""BankDemo.BankAccount");


        
public BankAccountAccessor(object target)
        {
            _privateObject 
= new PrivateObject(target, _privateType);
        }


        
public static object CreatePrivate(float initialBalance)
        {
            
object[] args = new object[] { initialBalance };
            PrivateObject priv_obj 
= new PrivateObject("BankDemo""BankDemo.BankAccount"new System.Type[] { typeof(float) }, args);
            
return priv_obj.Target;
        }

        
public float DepositMoney(float depositAmount)
        {
            
object[] args = new object[] { depositAmount };

            
return ((float)(_privateObject.Invoke("DepositMoney"new Type[] { typeof(float) }, args)));
        }

        
public float WithdrawMoney(float withdrawAmount)
        {
            
object[] args = new object[] { withdrawAmount };

            
return ((float)(_privateObject.Invoke("WithdrawMoney"new Type[] { typeof(float) }, args)));
        }

        
public static float BankAsset()
        {
            
object[] args = new object[0];

            
return ((float)(_privateType.InvokeStatic("BankAsset"new System.Type[0], args)));
        }

        
public float CurrentBalance
        {
            
get {     return ((float)(_privateObject.GetProperty("CurrentBalance")));     }

            
set {     _privateObject.SetProperty("CurrentBalance", value);     }
        }

        
public static int GetUniqueAccountNo
        {
            
get {     return ((int)(_privateType.GetStaticProperty("GetUniqueAccountNo")));     }
        }

        public int _accountNo
        {
            get { return ((int)(_privateObject.GetField("_accountNo"))); }

            set { _privateObject.SetField("_accountNo", value); }
        }
    }
}

 

========单元测试就是如下(这里仅仅举其中一个私有方法测试为例):========

 

[TestMethod()]
public void WithdrawMoneyTest()
{
            
float initBalance = 5000f;
            
object param0 = BankAccountAccessor.CreatePrivate(initBalance);
            BankAccountAccessor target 
= new BankAccountAccessor(param0);
            
float withdrawAmount = 100F;
            
float expected = initBalance - withdrawAmount;
            
float actual;
            actual 
= target.WithdrawMoney(withdrawAmount);
            Assert.AreEqual(expected, actual);
}


 

 

posted on 2008-07-24 19:28  Chr☆s  阅读(365)  评论(0编辑  收藏  举报