2012-07-22 48 views
2

我的單元測試工作,但在我添加了一些代碼來從web.config文件中的自定義配置部分獲取值後,單元測試停止工作。以下是我的代碼,那些標有「// new」的行是我添加的新代碼,並且它們打破了測試。在web.config文件中的自定義配置節打破我的單元測試

public partial class AccountController : Controller 
{ 
    private readonly string _twitterConsumerKey; 
    private readonly string _twitterConsumerSecret; 
    private readonly string _twitterAccessToken; 
    private readonly string _twitterAccessTokenSecret; 

    private readonly IUserService _userService; 

    public AccountController(IUserService userService) 
    { 
     if (userService == null) 
      throw new ArgumentNullException("userService"); 


     _userService = userService; 

     _twitterConsumerKey = TwitterSettings.Settings.ConsumerKey; //new code 
     _twitterConsumerSecret = TwitterSettings.Settings.ConsumerSecret; //new code 
     _twitterAccessToken = TwitterSettings.Settings.AccessToken; //new code 
     _twitterAccessTokenSecret = TwitterSettings.Settings.AccessTokenSecret; //new code 

    } 





public class TwitterSettings : ConfigurationSection 
{ 

    private static TwitterSettings settings = ConfigurationManager.GetSection("Twitter") as TwitterSettings; 
    public static TwitterSettings Settings { get { return settings; } } 

    [ConfigurationProperty("ConsumerKey", IsRequired = true)] 
    public string ConsumerKey 
    { 
     get { return (string)this["ConsumerKey"]; } 
     set { this["ConsumerKey"] = value; } 
    } 

    [ConfigurationProperty("ConsumerSecret", IsRequired = true)] 
    public string ConsumerSecret 
    { 
     get { return (string)this["ConsumerSecret"]; } 
     set { this["ConsumerSecret"] = value; } 
    } 


    [ConfigurationProperty("AccessToken", IsRequired = true)] 
    public string AccessToken 
    { 
     get { return (string)this["AccessToken"]; } 
     set { this["AccessToken"] = value; } 
    } 

    [ConfigurationProperty("AccessTokenSecret", IsRequired = true)] 
    public string AccessTokenSecret 
    { 
     get { return (string)this["AccessTokenSecret"]; } 
     set { this["AccessTokenSecret"] = value; } 
    } 


} 

當我在我的單元測試中調用此控制器時。我得到以下錯誤消息:「失敗:System.NullReferenceException:對象引用未設置爲對象的實例」。我是否需要創建一個ISetting接口?

[Test] 
    public void Login_Action_Get_Returns_Login_View() 
    { 
     // Arrange 

     var expectedViewName = "~/Views/Account/Login.cshtml"; 

     // it breaks here. 
     _accountController = new AccountController(_userService.Object, _mappingService.Object, _authenticationService.Object); 

     // Act 

     var result = _accountController.Login() as ViewResult; 

     // Assert 

     Assert.AreEqual(expectedViewName, result.ViewName, "View name should be {0}", expectedViewName); 
    } 

回答

7

尼斯的做法是在隔離測試單位。這也意味着抽象的環境 - 數據庫,文件系統(包括配置文件),等等。所以,從你的TwitterSettings類提取TwitterSettings接口:

public interface ITwitterSettings 
{ 
    string ConsumerKey { get; set; } 
    string ConsumerSecret { get; set; } 
    string AccessToken { get; set; } 
    string AccessTokenSecret { get; set; } 
} 

落實設置這個接口:

public class TwitterSettings : ConfigurationSection, ITwitterSettings 

並且將這種依賴性注入到控制器中:

public partial class AccountController : Controller 
{ 
    private readonly IUserService _userService; 
    private readonly ITwitterSettings _twitterSettings; 

    public AccountController(IUserService userService, 
          ITwitterSettings twitterSettings) 
    { 
     if (userService == null) 
      throw new ArgumentNullException("userService");  

     _userService = userService; 
     _twitterSettings = twitterSettings; 
    } 
} 

順便說一句環境的抽象使測試運行更快,並且測試wi只有在你的SUT邏輯被破壞的情況下,如果數據庫服務器沒有響應,或者沒有找到web.config,這種情況纔會失敗。

+0

感謝您回答我所有的單元測試問題。現在在這之後,我覺得我使用它非常舒服。 – qinking126 2012-07-23 16:05:50

2

單元測試項目不會使用MVC項目的web.config文件,因爲它正在運行它自己的應用程序上下文。

在測試項目的根目錄下創建一個App.Config文件,然後將自定義配置節添加到它。現在運行你的控制器測試,看看它是否工作。這不是一個適當的單元測試,但它會證明您的自定義代碼確實有效。

如果要測試實際web.config文件的有效性,您必須編寫其他幫助程序方法。

This link may help

+0

我認爲lazyberezovsky的解決方案更好。你的建議會起作用,但我最終維護了2份配置文件。但感謝您的幫助。 – qinking126 2012-07-23 16:08:13