Skip to content

Instantly share code, notes, and snippets.

@LeeCampbell
Created September 7, 2011 10:39
Show Gist options
  • Save LeeCampbell/1200249 to your computer and use it in GitHub Desktop.
Save LeeCampbell/1200249 to your computer and use it in GitHub Desktop.
Prebuilt Stub RegionManager to enable friction-free testing of the IRegionManager Prism interface
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.ServiceLocation;
using Moq;
using System.Collections.ObjectModel;
namespace ArtemisWest.Prism.Testing
{
public sealed class StubRegionManager : IRegionManager, IDisposable
{
private readonly StubRegionCollection _regions = new StubRegionCollection();
private readonly bool _locatorSet;
public StubRegionManager()
{
ChildRegionManager = this;
}
/// <summary>
/// If using this ctor you need to call Dispose at the end of each test.
/// </summary>
/// <param name="serviceLocator"></param>
public StubRegionManager(StubServiceLocator serviceLocator)
: this()
{
var regionViewRegistryMock = new Mock<IRegionViewRegistry>();
regionViewRegistryMock.Setup(
rvr => rvr.RegisterViewWithRegion(It.IsAny<string>(), It.IsAny<Func<object>>())).Callback(
(string regionName, Func<object> getContentDelegate) => Regions[regionName].Add(getContentDelegate()));
serviceLocator.RegisterInstance(regionViewRegistryMock.Object);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
_locatorSet = true;
}
public Mock<IRegion> SetupStubRegion(string regionName, ref StubViewCollection views)
{
var region = new Mock<IRegion>();
views = new StubViewCollection();
region.Setup(r => r.Name).Returns(regionName);
region.Setup(r => r.Views).Returns(views);
Regions.Add(region.Object);
return region;
}
public Mock<IRegion> CreateRegion(string name)
{
var regionMock = new Mock<IRegion>();
var views = new StubViewCollection();
var activeViews = new StubViewCollection();
regionMock.SetupGet(r => r.Name).Returns(name);
regionMock.SetupGet(r => r.Views).Returns(views);
regionMock.SetupGet(r => r.ActiveViews).Returns(activeViews);
regionMock.Setup(r => r.Add(It.IsAny<object>()))
.Returns(this)
.Callback((object view) => views.Add(view));
regionMock.Setup(r => r.Activate(It.IsAny<object>()))
.Callback((object view) => activeViews.Insert(0,view));
regionMock.Setup(r => r.Remove(It.IsAny<object>()))
.Callback((object v) =>
{
if (views.Contains(v))
views.Remove(v);
});
Regions.Add(regionMock.Object);
return regionMock;
}
/// <summary>
/// This allows you to set a property for the <see cref="CreateRegionManager"/> method.
/// </summary>
public IRegionManager ChildRegionManager { get; set; }
#region IRegionManager implementation
public IRegionManager CreateRegionManager()
{
return ChildRegionManager;
}
public IRegionCollection Regions
{
get { return _regions; }
}
#endregion
#region IDisposable implementation
public void Dispose()
{
Cleanup();
GC.SuppressFinalize(this);
}
~StubRegionManager()
{
Cleanup();
}
private void Cleanup()
{
if (_locatorSet)
{
// this basically set the service locator to a delegate that will throw if accessed. the intent here
// is we dont know the state of the locater if ServiceLocator.SetLocatorProvider has been accessed more
// than once without calling dispose.
ServiceLocator.SetLocatorProvider(() => { throw new Exception("ServiceLocator reset during testing"); });
}
}
#endregion
}
public class StubRegionCollection : IRegionCollection
{
private readonly Dictionary<string, IRegion> _regions = new Dictionary<string, IRegion>();
#region IRegionCollection Members
public IEnumerator<IRegion> GetEnumerator()
{
return _regions.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(IRegion region)
{
_regions.Add(region.Name, region);
}
public bool Remove(string regionName)
{
return _regions.Remove(regionName);
}
public bool ContainsRegionWithName(string regionName)
{
return _regions.ContainsKey(regionName);
}
public IRegion this[string regionName]
{
get { return _regions[regionName]; }
}
#endregion
public event NotifyCollectionChangedEventHandler CollectionChanged;
}
public class StubViewCollection : ObservableCollection<object>, IViewsCollection
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment