how do you mock an xml for unit testing? - unit-testing

I need to unit testing this GetData method.
public MessageResponse GetData(XmlElement requestElement)
{
MessageResponse MsgResponse = new MessageResponse();
if (requestElement.Attributes["employeeNo"] == null){
MsgResponse.Messages = new List<string>();
MsgResponse.Messages.Add("Attribute employeeNo is missing");
MsgResponse.Error = true;
return MsgResponse;
}
if (requestElement.Attributes["xmlEmployeeName"] == null){
MsgResponse.Messages.Add("Attribute xmlEmployeeName is missing");
MsgResponse.Error = true;
return MsgResponse;
}
return MsgResponse;
}
this method needs a XmlElement parameter. how do I mock it? in my code, I first created a xmlDocument, then load the xml file.
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
requestElement = doc.DocumentElement;
for me to test it, first i need to create a xml file without employeeNo, the create antoher one without name, maybe alot more for other scenarios. it just seems like alot work. is there a better way to test it?
should I use moq or other testing framework to simplify the testing?

You can just create the element you want to test with, w/o reading a file at all:
var doc = new XmlDocument();
doc.LoadXml("<MyTestElement/>");
var myTestElement = doc.DocumentElement;
myTestElement.Attributes["employeeNo"] = "fakeId";
var response = myTestResponder.GetData(myTestElement);
//assert whatever you need to
NOTE: every time you find out that the test is too hard to write, usually this means that your class/method does too much.
I would assume, that your method verifies the input, than does something with the data provided. I would suggest that you abstract the data reading part (using some xml deserializer) to populate the data model you need for your application.
Then run validation on the result of the deserialized data. Something like:
public MessageResponse GetData(XmlElement requestElement)
{
var data = _xmlDeserializer.Deserialize(requestElement);
var validationResult = _validator.Validate(data);
if (validationResult.Errors.Count > 0)
{
//populate errors
return result;
}
_dataProcessor.DoSomethingWithData(data);
}
Take a look at FluentValidation for a nice validation library.
If you go the above route, then your tests will be much simpler.

[TestMethod]
public void GetData_Returns_Correct_Message_When_EmployeeNo_Is_Null()
{
var inputWithoutEmployeeNo = GetElement(#"<input></input>");
var actual = GetData(inputWithoutEmployeeNo);
Assert.IsTrue(actual.Error, "Error should be true when employee no. is missing");
Assert.IsNotNull(actual.Messages);
Assert.AreEqual(1, actual.Messages.Count);
Assert.AreEqual("Attribute employeeNo is missing", actual.Messages[0]);
}
private XmlElement GetElement(string xml)
{
var doc = new XmlDocument();
doc.LoadXml(xml);
return doc.DocumentElement;
}
While working on the unit test, I found out that the code throws a NullReferenceException.
The following unit test demonstrates the issue:
[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GetData_Throws_NullReferenceException_When_EmployeeNo_Is_Not_Null_And_XmlEmployeeName_Is_Null()
{
var inputWithoutEmployeeNo = GetElement(#"<input employeeNo='123'></input>");
GetData(inputWithoutEmployeeNo);
}

Using Moq
using System;
using System.Xml;
using Moq;
using NUnit.Framework;
namespace MockXmlTest
{
[TestFixture]
public class MyServiceTests
{
private MockSetup _mockSetup;
[SetUp]
public void Init()
{
_mockSetup = MockSetup.HappySetup();
}
[Test]
public void MyService_Should_Return_Guid()
{
//Arrange
var myService = _mockSetup.MyService.Object;
var id = 42;
var expected = Guid.Empty.ToString();
//Act
var actual = myService.GetXml(id);
//Assert
Assert.AreEqual(expected, actual.FirstChild.InnerText);
}
}
public class MyService : IMyService
{
public XmlDocument GetXml(int id)
{
var doc = new XmlDocument();
//Do real stuff
return doc;
}
}
public interface IMyService
{
XmlDocument GetXml(int id);
}
public class MockSetup
{
public Mock<IMyService> MyService { get; set; }
public MockSetup()
{
MyService = new Mock<IMyService>();
}
public static MockSetup HappySetup()
{
var mockSetup = new MockSetup();
var mockDoc = CreateMockDoc();
//Matches any id of an integer, returns a XmlDocument mock
mockSetup.MyService.Setup(m => m.GetXml(It.IsAny<int>())).Returns(mockDoc);
return mockSetup;
}
private static XmlDocument CreateMockDoc()
{
//<Main><MyGuid>00000000-0000-0000-0000-000000000000</MyGuid></Main>
XmlDocument mockDoc = new XmlDocument();
XmlElement el = (XmlElement)mockDoc.AppendChild(mockDoc.CreateElement("Main"));
el.AppendChild(mockDoc.CreateElement("MyGuid")).InnerText = It.IsAny<Guid>().ToString();
return mockDoc;
}
}
}

Related

Mocking OData service endpoint

I am trying to mock the OData service context using Moq to return a list of dummy entities so that I could base my unit test on that. I cannot expose my real model and application so I have created this simulated app and the portion, which I have exposed is similar.
MyOdataApplication consuming ODataEndpoint which I am testing.
public class MyApplication
{
private readonly IODataContext _odataContext;
public MyApplication(IODataContext odataContext){
_odataContext = odataContext;
}
public async Task<IEnumerable<Book>> GetBooks(string authorName)
{
IEnumerable<Book> books = null;
var query = (DataServiceQuery<Book>)_odataContext.Books.Where(x => x.Author = authorName);
books = await query.ExecuteAsync().ToList();
return books;
}
public bool async ValidateBooks(string authorName){
var books = await GetBooks(authorname);
//other code....
}
}
My Odata Service contract interface is
public interface IODataContext
{
global::Microsoft.OData.Client.DataServiceQuery<global::models.Book> Books { get; }
}
My Unit Test class is as follows.
[TestFixture]
public class MyTestClass
{
[Test]
public void TestOdataFunctionality()
{
var mockODataEndpoint = new Mock<IODataContext>();
//It fails here as its not able to convery IQueryable<Book> to DataServiceQuery<Book>
mockODataEndpoint.Setup(x => x.GetBooks(It.IsAny<string>)).Returns(GetDummyBooks());
var myApp = new MyApplication(mockODataEndpoint.Object);
//This is my main method which I need to test.
Task<bool> task = myApp.ValidateBooks("author name");
var isvalid = task.Result;
Assert.AreEqual(true, isvalid);
}
private DataServiceQuery<Book>GetDummyBooks()
{
var books = new List<Book>
{
new Book()
{
Name = "Book1",
Author = "author name",
//other properties...
}
};
//Not sure how to achieve this. The below line is giving error ???
return (DataServiceQuery<Book>)books.AsQueryable();
}
}
How do I mock the Odata Service endpoint so that I could test my ValidateBooks method?

How do I perform integration test on WebApi controller using FakeItEasy?

I am new at implementing unit tests and integration tests. I am trying to write some integration tests for my application.
Following are the code snippets from my application to give you all the idea of my code.
It would be great help if you could provide me some guidance for it.
namespace MyApplication.ApiControllers
{
[Authorize]
[RoutePrefix("api/customers")]
[AppExceptionFilter]
public class CustomersController : ApiController
{
private readonly IMediator _mediator;
public CustomersController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
[Route("GetCustomer")]
public async Task<IHttpActionResult> GetCustomer(string customerNumber, string customerType = null)
{
var result = await _mediator.RequestAsync(new GetCustomerRequest(customerNumber, customerType));
return Ok(result);
}
}
}
Following is the implementation for GetCustomerRequest handler
public async Task<List<Customer>> HandleAsync(GetCustomerRequest request)
{
var result = await customerService.GetCustomer(request.CustomerNumber, request.CustomerType);
// some business logic
return result;
}
Following is the implementation for customerService
public async Task<List<Customer>> GetCustomer(string customerNumber, string customerType = null)
{
using (var dataContext = _dataContextFactory.Invoke())
{
result = await dataContext.Customers
.Where(b => b.CustomerNumber == customerNumber)
.Where(b => b.CustomerType == customerType)
.Select(b => new Customer
{
// Properties assignment...
})
.ToListAsync();
}
return result;
}
Below is the integration unit test what I have tried.
namespace MyApplication.Tests.Integrations
{
[TestFixture]
public class CustomersControllerTests
{
private string _baseAddress;
private string _username;
private string _password;
private IApiClient _apiClient;
[SetUp]
public void Setup()
{
_baseAddress = "https://mywebaaplication.com"; // TODO get this from a config
_username = "";
_password = "";
_apiClient = new ApiClient(new ApiClientAuthenticationHandler(), _baseAddress); // REPLACE with AzureADApiClientAuthenticationHandler
}
[Test]
public async Task CustomersController_GetCustomer()
{
var customerNumber = string.Empty;
var customerType = 500;
var result = await _apiClient.GetAsync<Customer[]>($"/api/customers/GetCustomer?customerNumber={customerNumber}&customerType={customerType}");
Assert.IsNotNull(result);
Assert.IsTrue(result?.Length > 0);
}
}
}
You can do a few things:
Create a webhost within your unit test, then do http requests against it
Not test your controller in a unit test, but in a liveness/readiness check (because it's just glue code anyway). Just do integration testing for your service.
Just test against "new CustomersController"
There isn't a right/wrong answer here. You just look at the risks, and test accordingly. Also depends on the type of code-changes you expect. Sometimes its fine to create the test only within the context of a new change, no need to anticipate everything.

How to write unit test for ActionFilter when using Service Locator

I am planning to write an ActionFilter for business validation and in which some services will be resolved via Service Locator(I know this is not good practice and as far as possible i avoid Service Locator pattern, but for this case i want to use it).
OnActionExecuting method of the filter is something like this:
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
// get validator for input;
var validator = actionContext.HttpContext.RequestServices.GetService<IValidator<TypeOfInput>>();// i will ask another question for this line
if(!validator.IsValid(input))
{
//send errors
}
}
Is it possible to write unit test for above ActionFilterand how?
Here is an sample on how to create a mock (using XUnit and Moq framework) to verify that the IsValid method is called and where the mock returns an false.
using Dealz.Common.Web.Tests.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using System;
using Xunit;
namespace Dealz.Common.Web.Tests.ActionFilters
{
public class TestActionFilter
{
[Fact]
public void ActionFilterTest()
{
/****************
* Setup
****************/
// Create the userValidatorMock
var userValidatorMock = new Mock<IValidator<User>>();
userValidatorMock.Setup(validator => validator
// For any parameter passed to IsValid
.IsValid(It.IsAny<User>())
)
// return false when IsValid is called
.Returns(false)
// Make sure that `IsValid` is being called at least once or throw error
.Verifiable();
// If provider.GetService(typeof(IValidator<User>)) gets called,
// IValidator<User> mock will be returned
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock.Setup(provider => provider.GetService(typeof(IValidator<User>)))
.Returns(userValidatorMock.Object);
// Mock the HttpContext to return a mockable
var httpContextMock = new Mock<HttpContext>();
httpContextMock.SetupGet(context => context.RequestServices)
.Returns(serviceProviderMock.Object);
var actionExecutingContext = HttpContextUtils.MockedActionExecutingContext(httpContextMock.Object, null);
/****************
* Act
****************/
var userValidator = new ValidationActionFilter<User>();
userValidator.OnActionExecuting(actionExecutingContext);
/****************
* Verify
****************/
// Make sure that IsValid is being called at least once, otherwise this throws an exception. This is a behavior test
userValidatorMock.Verify();
// TODO: Also Mock HttpContext.Response and return in it's Body proeprty a memory stream where
// your ActionFilter writes to and validate the input is what you desire.
}
}
class User
{
public string Username { get; set; }
}
class ValidationActionFilter<T> : IActionFilter where T : class, new()
{
public void OnActionExecuted(ActionExecutedContext context)
{
throw new NotImplementedException();
}
public void OnActionExecuting(ActionExecutingContext actionContext)
{
var type = typeof(IValidator<>).MakeGenericType(typeof(T));
var validator = (IValidator<T>)actionContext.HttpContext
.RequestServices.GetService<IValidator<T>>();
// Get your input somehow
T input = new T();
if (!validator.IsValid(input))
{
//send errors
actionContext.HttpContext.Response.WriteAsync("Error");
}
}
}
internal interface IValidator<T>
{
bool IsValid(T input);
}
}
HttpContextUtils.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Collections.Generic;
namespace Dealz.Common.Web.Tests.Utils
{
public class HttpContextUtils
{
public static ActionExecutingContext MockedActionExecutingContext(
HttpContext context,
IList<IFilterMetadata> filters,
IDictionary<string, object> actionArguments,
object controller
)
{
var actionContext = new ActionContext() { HttpContext = context };
return new ActionExecutingContext(actionContext, filters, actionArguments, controller);
}
public static ActionExecutingContext MockedActionExecutingContext(
HttpContext context,
object controller
)
{
return MockedActionExecutingContext(context, new List<IFilterMetadata>(), new Dictionary<string, object>(), controller);
}
}
}
As you can see, it's quite a mess, you need to create plenty of mocks to simulate different responses of the actuall classes, only to be able to test the ActionAttribute in isolation.
I like #Tseng's above answer but thought of giving one more answer as his answer covers more scenarios (like generics) and could be overwhelming for some users.
Here I have an action filter attribute which just checks the ModelState and short circuits(returns the response without the action being invoked) the request by setting the Result property on the context. Within the filter, I try to use the ServiceLocator pattern to get a logger to log some data(some might not like this but this is an example)
Filter
public class ValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<ValidationFilterAttribute>>();
logger.LogWarning("some message here");
context.Result = new JsonResult(new InvalidData() { Message = "some messgae here" })
{
StatusCode = 400
};
}
}
}
public class InvalidData
{
public string Message { get; set; }
}
Unit Test
[Fact]
public void ValidationFilterAttributeTest_ModelStateErrors_ResultInBadRequestResult()
{
// Arrange
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock
.Setup(serviceProvider => serviceProvider.GetService(typeof(ILogger<ValidationFilterAttribute>)))
.Returns(Mock.Of<ILogger<ValidationFilterAttribute>>());
var httpContext = new DefaultHttpContext();
httpContext.RequestServices = serviceProviderMock.Object;
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
var actionExecutingContext = new ActionExecutingContext(
actionContext,
filters: new List<IFilterMetadata>(), // for majority of scenarios you need not worry about populating this parameter
actionArguments: new Dictionary<string, object>(), // if the filter uses this data, add some data to this dictionary
controller: null); // since the filter being tested here does not use the data from this parameter, just provide null
var validationFilter = new ValidationFilterAttribute();
// Act
// Add an erorr into model state on purpose to make it invalid
actionContext.ModelState.AddModelError("Age", "Age cannot be below 18 years.");
validationFilter.OnActionExecuting(actionExecutingContext);
// Assert
var jsonResult = Assert.IsType<JsonResult>(actionExecutingContext.Result);
Assert.Equal(400, jsonResult.StatusCode);
var invalidData = Assert.IsType<InvalidData>(jsonResult.Value);
Assert.Equal("some messgae here", invalidData.Message);
}

Unit Test Assert against end result or verifying whether the parameters were called using Moq

Below is a class (Class1) that I want to test, but I'm not fully satisfied with my Unit Test. Please see below code samples.
System Under Test
public interface IRepository {
string GetParameter(int id);
}
public class Repository {
public string GetParameter(int id) {
return "foo";
}
}
public class ErrorInfo {
public string ErrorCodes { get; set; }
}
public interface IErrorProvider {
ErrorInfo BuildErrorMessage(string errorCodes);
}
public class ErrorProvider {
public ErrorInfo BuildErrorMessage(string errorCodes) {
return new ErrorInfo(){ErrorCodes = errorCodes};
}
}
public class Class1 {
private readonly IRepository _repository;
private readonly IErrorProvider _errorProvider;
public Class1(IRepository repository, IErrorProvider errorProvider) {
_repository = repository;
_errorProvider = errorProvider;
}
public List<ErrorInfo> GetErrorList(int id) {
var errorList = new List<ErrorInfo>();
string paramName = _repository.GetParameter(id);
if (string.IsNullOrEmpty(paramName)) {
string errorCodes = string.Format("{0}, {1}", 200, 201);
var error = _errorProvider.BuildErrorMessage(errorCodes);
errorList.Add(error);
}
return errorList;
}
}
Unit Tests
Below test passes and we check whether the correct error codes being used within the system under test.
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes2() {
//Arrange
var stubRepo = new Mock<IRepository>();
stubRepo.Setup(x => x.GetParameter(It.IsAny<int>())).Returns(string.Empty);
var stubErrorMock = new Mock<IErrorProvider>();
const int id = 5;
var sut = new Class1(stubRepo.Object, stubErrorMock.Object);
//Act
var result = sut.GetErrorList(id);
//Verify
string verifiableErrorCodes = "200, 201";
stubErrorMock.Verify(x => x.BuildErrorMessage(verifiableErrorCodes));
}
However I would prefer testing the end result. For example, I want to Assert against the error codes that have been used in the production code. Below test fails but I like to know your thoughts on how to Assert against the errorCodes that has been used in the system under test.
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes1() {
//Arrange
var stubRepo = new Mock<IRepository>();
stubRepo.Setup(x => x.GetParameter(It.IsAny<int>())).Returns(string.Empty);
string expectedErrorCodes = "200, 201";
var stubErrorRepo = new Mock<IErrorProvider>();
stubErrorRepo.Setup(e => e.BuildErrorMessage(It.IsAny<string>()));
const int id = 5;
var sut = new Class1(stubRepo.Object, stubErrorRepo.Object);
//Act
var result = sut.GetErrorList(id);
//Assert
Assert.AreEqual(expectedErrorCodes, result.Single().ErrorCodes);
}
What would be the correct way to test this error codes that has been used in the system?
I suggest to mock only the IRepository and use a real IErrorProvider. Then you can call GetErrorList(id) and check the result.
There is not really right or wrong answer and we have decided to use the Assert test as it test the end result.
I took the TDD approach and re-implemented/analysed as below.
Start with a failing test (to simplify the code I removed the Repository from both test and the sut)
//AssertTest
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes1()
{
//Arrange
const string expectedErrorCodes = "200, 201";
var stubErrorRepo = new Mock<IErrorProvider>();
stubErrorRepo.Setup(e => e.BuildErrorMessage(expectedErrorCodes)).Returns(new ErrorInfo() { ErrorCodes = expectedErrorCodes });
var sut = new Class1(stubErrorRepo.Object);
//Act
var result = sut.GetErrorList();
//Assert
Assert.AreEqual(expectedErrorCodes, result.Single().ErrorCodes);
}
//SUT
public IEnumerable<ErrorInfo> GetErrorList(int id)
{
yield return new ErrorInfo();
}
As you would expect the test fail.
Now if write enough production code to make this test pass.
public IEnumerable<ErrorInfo> GetErrorList()
{
yield return _errorProvider.BuildErrorMessage("200, 201");
}
The VerifyTest would still fail for the above SUT.
//VerifyTest
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes2()
{
//Arrange
var stubErrorMock = new Mock<IErrorProvider>();
var sut = new Class1(stubErrorMock.Object);
//Act
sut.GetErrorList();
//Verify
string verifiableErrorCodes = "200, 201";
stubErrorMock.Verify(x => x.BuildErrorMessage(verifiableErrorCodes));
}
However if I want this test to pass, I can write the below production code as below
public IEnumerable<ErrorInfo> GetErrorList()
{
_errorProvider.BuildErrorMessage("200, 201");
return null;
}
Now the VerifyTest passes, but the AssertTest fails.
Both tests are valid in their own ways. However they test different semantics.
AssertTest test whether the end result contains the correct error codes. Verify test ensures
the method is called with the correct error codes. It is important to note that
the end value of the Assert test is based on the setup method "match" provided by the Moq
framework. In other words the setup dictates what the end result would be.
AssertTest would fail if the setup is configured incorrectly or the production code uses error codes that does not match the setup configuration.
It is preferred to use the AssertTest as it test the end result.

Is it possible to unit test BundleConfig in MVC4?

As far as I can tell, the answer is no. The issue I'm seeing comes from the Include(params string[]) method in the System.Web.Optimization.Bundle class. Internally this invokes System.Web.Optimization.IncludeDirectory(string, string, bool), which in turn uses this code:
DirectoryInfo directoryInfo = new DirectoryInfo(
HttpContext.Current.Server.MapPath(directoryVirtualPath));
While it is possible to set HttpContext.Current during a unit test, I can't figure out how to make its .Server.MapPath(string directoryVirtualPath) return a non-null string. Since the DirectoryInfo(string) constructor throws an exception when passed a null argument, such a test will always fail.
What is the .NET team's recommendation for this? Do we have to unit test bundling configurations as part of integration tests or user acceptance tests?
I have some good news for you, for RTM we added a new static property on BundleTable to enable more unit tests:
public static Func<string, string> MapPathMethod;
Edit Updated with a test virtual path provider:
So you can do something like this:
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;
}
}
}
And then write a unit test using that like so:
[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);
}
In .Net 4.5 things have slightly changed. Here is a working version of the approved answer updated to accommodate these changes (I am using Autofac). Note the "GenerateBundleResponse" instead of "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);
}