web.config文件中的Custom Config部分会破坏我的单元测试

时间:2012-07-22 22:25:55

标签: c# asp.net-mvc-3 unit-testing

我的单元测试工作正常,但在我添加了一些代码以从web.config文件中的Custom Config部分获取值之后,单元测试停止工作。以下是我的代码,那些标有“// new”的行是我添加的新代码,它们会破坏测试。

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);
    }

2 个答案:

答案 0 :(得分: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;
    }   
}

BTW抽象环境使测试运行得更快,只有当您的SUT逻辑中断时,测试才会失败,而不是数据库服务器没有响应,或者找不到web.config。

答案 1 :(得分:2)

单元测试项目不会使用MVC项目的web.config文件,因为它正在运行它自己的应用程序上下文。

在测试项目的根目录中创建一个App.Config文件,并将自定义配置部分添加到其中。立即运行您的控制器测试,看它是否有效。这不是一个正确的单元测试,但它将证明您的自定义代码确实有效。

如果要测试实际web.config文件的有效性,则必须编写其他辅助方法。

This link may help