unit-testing - net - testing controllers
¿Es posible probar BundleConfig en MVC4? (2)
Tengo buenas noticias para ti, para RTM hemos agregado una nueva propiedad estática en BundleTable
para habilitar más pruebas unitarias:
public static Func<string, string> MapPathMethod;
Editar actualizado con un proveedor de ruta virtual de prueba:
Entonces puedes hacer algo como esto:
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;
}
}
}
Y luego, escribe una prueba unitaria usando eso así:
[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);
}
Por lo que puedo decir, la respuesta es no. El problema que estoy viendo proviene del método Include(params string[])
en la clase System.Web.Optimization.Bundle
. Internamente esto invoca System.Web.Optimization.IncludeDirectory(string, string, bool)
, que a su vez usa este código:
DirectoryInfo directoryInfo = new DirectoryInfo(
HttpContext.Current.Server.MapPath(directoryVirtualPath));
Si bien es posible establecer HttpContext.Current
durante una prueba de unidad, no puedo averiguar cómo hacer que su .Server.MapPath(string directoryVirtualPath)
devuelva una cadena no nula. Como el constructor DirectoryInfo(string)
arroja una excepción cuando pasa un argumento nulo, dicha prueba siempre fallará.
¿Cuál es la recomendación del equipo de .NET para esto? ¿Tenemos que probar las configuraciones de agrupación de prueba como parte de las pruebas de integración o las pruebas de aceptación del usuario?
En .Net 4.5 las cosas han cambiado ligeramente. Aquí hay una versión de trabajo de la respuesta aprobada actualizada para acomodar estos cambios (estoy usando Autofac). Tenga en cuenta el "GenerateBundleResponse" en lugar de "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);
}