2013-06-11 113 views
0

數據訪問我想請問我該如何使用犀牛嘲弄在下面的例子中:如何嘲笑的私有方法

Public Class CustomerService 
    { 
     Public void Register() 
    { 
     Action1(); 
     Action2(); 
    } 

    private action1() 
    { 
     //this is a call to other dll. 
     var isExist = _dataComponentService.CheckIfUserExist(userName); 
    } 
    private action2() 
    { 
     //do some more work... 
     // Call to dataComponentService. write some data in the database.... 
    } 
    } 

這只是爲真正的代碼,我需要更新的例子。 當前的單元測試正在對數據庫服務進行真正的調用。 我想編寫一個單元測試,用於檢查公共Register()中的行爲,而不需要對數據庫服務進行真正的調用。

是否可以嘲弄對位於私人方法中的其他組件的調用,而無需重新編寫洞服務?

感謝你在先進

大利

+0

您應該使用依賴注入爲'CustomerService'類提供'dataComponentService'對象。我建議使用構造函數注入。在應用程序運行時期間,'dataComponentService'設置爲真正的數據庫訪問實例,但在測試場景中,您可以使用模擬對象。網上有很多關於DI與單元測試的文章,例如Mark Seemann的博客:[link](http://blog.ploeh.dk)。 – sgnsajgon

回答

3

你需要做一些依賴注入讓你的模擬到您的類下的測試(有關DI的更多信息,由Martin Fowler退房this article )。首先你的「dataComponentService」類需要實現一個接口:

public interface IDataComponentService 
{ 
    boolean CheckIfUserExist(String user); 
} 

然後你就可以通過添加適當的構造注入實現接口的類到您的CustomerService類:現在

public class CustomerService 
{ 
    private IDataComponentService _dataComponentService 

    // This constructor allows you to inject your dependency into the class 
    public CustomerService(IDataComponentService dataComponentService) 
    { 
     _dataComponentService = dataComponentService; 
    } 

    Public void Register() 
    { 
     Action1(); 
     Action2(); 
    } 

    private action1() 
    { 
     //this is a call to other dll. 
     var isExist = _dataComponentService.CheckIfUserExist(userName); 
    } 

    private action2() 
    { 
     //do some more work... 
     // Call to dataComponentService. write some data in the database.... 
    } 
} 

,在測試代碼您的測試,你可以創建一個IDataComponentService的模擬...

var dataComponentServiceMock = MockRepository.GenerateMock<IDataComponentService>(); 
//add mock's behavior here... 

......並把它傳遞到類被測因此...

var objUt = new CustomerService(dataComponentServiceMock); 
objUt.Register(); 
// check method calls to the mock here... 
+0

當您編寫測試時,您會測試公共方法。在這種情況下,我使用私有方法撥打其他服務。 – Ori

+0

謝謝你所有的答案。當你編寫測試時,你測試公共方法。在這種情況下,我使用私有方法撥打其他服務。問題是如何將其他服務的響應存根,以便在私有方法中代碼可以繼續制動?爲了測試一個期望在私有方法結束時的行爲。 – Ori

+0

您正在討論_dataComponentService服務的服務?如果是這樣,您可以將行爲添加到模擬中。如果你想測試私人方法裏面發生了什麼,我不確定你如何執行一些你可以測試的動作。或者,您可以使這些方法內部公開,並將它們公開給您的測試庫,詳情如下:http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx – mattyB

2

你的問題引起了我的一些懷疑。 一:如果單元測試正在執行數據庫訪問,則不是單元測試。如果它正在進行數據庫訪問,它更像是一個集成測試。二:你應該更多地依賴依賴注入,並開始對接口而不是對象進行編程。這意味着你注入了你必須定義的接口_datacomponentservice

在此之上。即使你有私人方法。你可以放鬆它,也許保護並使之虛擬化。如果它是虛擬的,您可以製作一個特殊的測試版本,以不同的方式實施受保護的成員。

許多人正在界定許多私人方法,但我發現有時這會阻礙未來的發展,我寧願讓他們受到保護而不是私人方式。因爲你永遠不知道未來會如何。我使用.NET反射器來瀏覽微軟的代碼,比如說一個組合框,希望使它更加靈活。有時候我有時會這樣做,因爲有些方法和類甚至在派生類中不可訪問。