2

我的单元测试有效,但是在我添加了一些代码以从 web.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:对象引用未设置为对象的实例”。我需要创建一个ISSetting接口吗???

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

2 回答 2

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 abstracting of environment makes tests run faster, and your tests will fail only if your SUT logic is broken, not if database server not responding, or web.config is not found.

于 2012-07-23T08:03:27.490 回答
2

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

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

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

此链接可能会有所帮助

于 2012-07-23T00:03:13.160 回答