1

下面我有一些我无法进行单元测试的代码,因为它试图从 IIS7 读取设置,不幸的是我们的夜间构建机器没有 IIS7。我唯一能想到的是将 ServerManager 传递给该方法,但是在调用者中我将再次拥有一个 ServerManager ,这将使该方法无法进行单元测试。我们将 MOQ 用于我们的 Mock 库。

        public ISection GetCurrentSettings(string location, Action<string> status)
    {
        #region Sanity Checks

        if (string.IsNullOrEmpty(location))
        {
            throw new ArgumentNullException("location");
        }
        if (status == null)
        {
            throw new ArgumentNullException("status");
        }
        #endregion

        ISection section = null;

        _logger.Debug(string.Format("Retrieving current IIS settings for app at {0}.", location));
        status("Getting current IIS settings.");
        using (ServerManager manager = new ServerManager())
        {
            var data = (from site in manager.Sites
                        from app in site.Applications
                        from vdir in app.VirtualDirectories
                        where vdir.PhysicalPath.Equals(location, StringComparison.CurrentCultureIgnoreCase)
                        select new {Website = site, App = app}).SingleOrDefault();

            if (data == null)
            {
                _logger.Debug(string.Format("Could not find an application at {0} in IIS. Going to load the defaults instead.", location));
                //ToDo possibly load defaults
            }
            else
            {
               _logger.Debug(string.Format("Application found in IIS with website: {0} and a path of {1}", data.Website.Name, data.App.Path));
                int port =
                    data.Website.Bindings.Where(b => b.EndPoint != null).Select(b => b.EndPoint.Port).Single();


                section = new IISSection
                    {
                        ApplicationPoolName = data.App.ApplicationPoolName,
                        VirtualDirectoryAlias = data.App.Path,
                        WebsiteName = data.Website.Name,
                        WebsiteRoot = data.App.VirtualDirectories[0].PhysicalPath,
                        Port = port.ToString(CultureInfo.InvariantCulture),
                        WillApply = true,
                        AnonymousUser = _userService.GetUserByType(UserType.Anonymous)
                    };
            }

            return section;

        }
4

2 回答 2

3

在不完全重写代码的情况下,一般的想法是传入一个 ISettingReader*(实现为 IisSettingReader),这将公开从 IIS 获取所需数据的方法。然后,您可以通过将 ISettingReader 传递给方法/类来存根 ISettingReader 以返回您需要的内容

*或者,IServerManager 似乎是当前名称,但我不确定这是否特定于 IIS

更新

更具体地说,正如 Darin Dimitrov 所阐述的,您需要将所有依赖项拉到方法之外,并通过参数/构造函数/属性注入传递它们。这将需要重写处于当前状态的代码。

如果没有(并且我确实建议重写),那么您可以使用 TypeMock 之类的东西,据说它可以伪造类内部的依赖关系,但我自己没有使用过它,只知道我读过的内容。

于 2012-09-24T16:28:07.257 回答
0

使用起订量

这将允许您创建 ISettings 的模拟版本,而不必创建真实版本。它还具有允许您指定自己的功能的额外优势。

于 2012-09-24T16:27:55.820 回答