Можно ли провести модульное тестирование BundleConfig в MVC4?

Насколько я могу судить, ответ - нет. Проблема, которую я вижу, исходит от Include(params string[]) метод в System.Web.Optimization.Bundle учебный класс. Внутренне это вызывает System.Web.Optimization.IncludeDirectory(string, string, bool), который в свою очередь использует этот код:

DirectoryInfo directoryInfo = new DirectoryInfo(
    HttpContext.Current.Server.MapPath(directoryVirtualPath));

Пока можно установить HttpContext.Current во время модульного теста я не могу понять, как сделать его .Server.MapPath(string directoryVirtualPath) вернуть ненулевую строку. Так как DirectoryInfo(string) Конструктор выдает исключение при передаче нулевого аргумента, такой тест всегда будет неудачным.

Какова рекомендация команды.NET для этого? Нужно ли нам объединять тестовые конфигурации в рамках интеграционных или приемочных тестов?

2 ответа

Решение

У меня есть для вас хорошие новости, для RTM мы добавили новое статическое свойство на BundleTable чтобы включить больше юнит-тестов:

public static Func<string, string> MapPathMethod;

Изменить Обновлено с тестовым поставщиком виртуального пути:

Так что вы можете сделать что-то вроде этого:

public class TestVirtualPathProvider : VirtualPathProvider {

    private string NormalizeVirtualPath(string virtualPath, bool isDirectory = false) {
        if (!virtualPath.StartsWith("~")) {
            virtualPath = "~" + virtualPath;
        }
        virtualPath = virtualPath.Replace('\\', '/');
        // Normalize directories to always have an ending "/"
        if (isDirectory && !virtualPath.EndsWith("/")) {
            return virtualPath + "/";
        }
        return virtualPath;
    }

    // Files on disk (virtualPath -> file)
    private Dictionary<string, VirtualFile> _fileMap = new Dictionary<string, VirtualFile>();
    private Dictionary<string, VirtualFile> FileMap {
        get { return _fileMap; }
    }

    public void AddFile(VirtualFile file) {
        FileMap[NormalizeVirtualPath(file.VirtualPath)] = file;
    }

    private Dictionary<string, VirtualDirectory> _directoryMap = new Dictionary<string, VirtualDirectory>();
    private Dictionary<string, VirtualDirectory> DirectoryMap {
        get { return _directoryMap; }
    }

    public void AddDirectory(VirtualDirectory dir) {
        DirectoryMap[NormalizeVirtualPath(dir.VirtualPath, isDirectory: true)] = dir;
    }

    public override bool FileExists(string virtualPath) {
        return FileMap.ContainsKey(NormalizeVirtualPath(virtualPath));
    }

    public override bool DirectoryExists(string virtualDir) {
        return DirectoryMap.ContainsKey(NormalizeVirtualPath(virtualDir, isDirectory: true));
    }

    public override VirtualFile GetFile(string virtualPath) {
        return FileMap[NormalizeVirtualPath(virtualPath)];
    }

    public override VirtualDirectory GetDirectory(string virtualDir) {
        return DirectoryMap[NormalizeVirtualPath(virtualDir, isDirectory: true)];
    }

    internal class TestVirtualFile : VirtualFile {
        public TestVirtualFile(string virtualPath, string contents)
            : base(virtualPath) {
            Contents = contents;
        }

        public string Contents { get; set; }

        public override Stream Open() {
            return new MemoryStream(UTF8Encoding.Default.GetBytes(Contents));
        }
    }

    internal class TestVirtualDirectory : VirtualDirectory {
        public TestVirtualDirectory(string virtualPath)
            : base(virtualPath) {
        }

        public List<VirtualFile> _directoryFiles = new List<VirtualFile>();
        public List<VirtualFile> DirectoryFiles {
            get {
                return _directoryFiles;
            }
        }

        public List<VirtualDirectory> _subDirs = new List<VirtualDirectory>();
        public List<VirtualDirectory> SubDirectories {
            get {
                return _subDirs;
            }
        }

        public override IEnumerable Files {
            get {
                return DirectoryFiles;
            }
        }

        public override IEnumerable Children {
            get { throw new NotImplementedException(); }
        }

        public override IEnumerable Directories {
            get { 
                return SubDirectories;
            }
        }
    }

А затем напишите модульный тест, используя это так:

    [TestMethod]
    public void StyleBundleCustomVPPIncludeVersionSelectsTest() {
        //Setup the vpp to contain the files/directories
        TestVirtualPathProvider vpp = new TestVirtualPathProvider();
        var directory = new TestVirtualPathProvider.TestVirtualDirectory("/dir/");
        directory.DirectoryFiles.Add(new TestVirtualPathProvider.TestVirtualFile("/dir/style1.0.css", "correct"));
        directory.DirectoryFiles.Add(new TestVirtualPathProvider.TestVirtualFile("/dir/style.css", "wrong"));
        vpp.AddDirectory(directory);

        // Setup the bundle
        ScriptBundle bundle = new ScriptBundle("~/bundles/test");
        bundle.Items.VirtualPathProvider = vpp;
        bundle.Include("~/dir/style{version}.css");

        // Verify the bundle repsonse
        BundleContext context = SetupContext(bundle, vpp);
        BundleResponse response = bundle.GetBundleResponse(context);
        Assert.AreEqual(@"correct", response.Content);
    }

В.Net 4.5 все немного изменилось. Вот рабочая версия утвержденного ответа, обновленная с учетом этих изменений (я использую Autofac). Обратите внимание на "GenerateBundleResponse" вместо "GetBundleResponse":

    [Fact]
    public void StyleBundleIncludesVersion()
    {
        //Setup the vpp to contain the files/directories
        var vpp = new TestVirtualPathProvider();
        var directory = new TestVirtualPathProvider.TestVirtualDirectory("/dir/");
        directory.DirectoryFiles.Add(new TestVirtualPathProvider.TestVirtualFile("/dir/style1.0.css", "correct"));
        directory.DirectoryFiles.Add(new TestVirtualPathProvider.TestVirtualFile("/dir/style.css", "wrong"));
        vpp.AddDirectory(directory);

        // Setup the bundle
        var bundleCollection = new BundleCollection();
        var bundle = new ScriptBundle("~/bundles/test");
        BundleTable.VirtualPathProvider = vpp;
        bundle.Include("~/dir/style{version}.css");
        bundleCollection.Add(bundle);
        var mockHttpContext = new Mock<HttpContextBase>();

        // Verify the bundle repsonse
        var context = new BundleContext(mockHttpContext.Object, bundleCollection, vpp.ToString());
        var response = bundle.GenerateBundleResponse(context);
        Assert.Equal(@"correct", response.Content);
    }
Другие вопросы по тегам