Unit Testing Pris V2 with Mocks from Rhino

Topics: Prism v2 - WPF 3.5
Sep 9, 2009 at 2:50 AM

My test is below :
        public void WhenInstantiated_ShouldRegisterIStatusBarViewWithRegionManager()
            var unity = MockRepository.GenerateStub<IUnityContainer>();
            var presenter = MockRepository.GenerateStub<IStatusBarViewPresenter>();
            var view = MockRepository.GenerateStub<IStatusBarView>();
            presenter.View = view;

            var eventAggregator = MockRepository.GenerateStub<IEventAggregator>();
            var regionManager = MockRepository.GenerateStub<IRegionManager>();
            var regionCollection = MockRepository.GenerateStub<IRegionCollection>();
            var region = MockRepository.GenerateStub<IRegion>();

            regionManager.Stub(r => r.Regions).Return(regionCollection);
            regionCollection.Add(RegionNames.StatusBarRegion, region);

            unity.Stub(container => container.Resolve<IEventAggregator>()).Return(eventAggregator);
            unity.Stub(container => container.Resolve<IRegionManager>()).Return(regionManager);
            unity.Stub(container => container.Resolve<IStatusBarViewPresenter>()).Return(presenter);

            new StatusBarModule(unity).Initialize(); // RegionManager.Regions doesn't contain any regions!!

            unity.AssertWasCalled(container => container.Resolve<IEventAggregator>());
            unity.AssertWasCalled(container => container.Resolve<IRegionManager>());
            unity.AssertWasCalled(container => container.Resolve<IStatusBarViewPresenter>());
            regionManager.AssertWasCalled(manager => manager.RegisterViewWithRegion(RegionNames.StatusBarRegion, () => presenter.View));

The part from the StatusBarModule that is pertinent is the following line:
RegionManager.RegisterViewWithRegion(RegionNames.StatusBarRegion, () => Container.Resolve<IStatusBarViewPresenter>().View);// RegionManager.Regions doesn't contain any regions!!
Any help would be greatly appreciated.

Sep 10, 2009 at 6:14 PM

Hi Bill,

You can mock the functionality related to adding regions as well in this test, since that is part of the Prism tests. I made a small modification to the code and tried if it worked in the immediate window by asking for: this.regionManager.Regions["MainRegion"], which gave me a non-null result. In order to get that working, I changed this line:

regionCollection.Add(RegionNames.StatusBarRegion, region);

For this one:

regionCollection.Stub(c =>c[RegionNames.StatusBarRegion]).Return(region);

Although this will make the Regions collection not empty, this might not make the test pass, as there is some functionality (such as the RegisterViewWithRegion) method that has not been mocked, and could throw a BadImageException.

You can take a look at the Unit Test in the different Prism Quickstarts and RI, which might provide some ideas for these mocks.

Please let me know if this helps.

Damian Schenkelman


Sep 10, 2009 at 8:16 PM

Thanks for that Dan.

I realized that there was an issue with Mocking/Stubing IUnityContainer.RegisterViewWithRegion because it is an extension method and Rhino does not provide any method for mocking extension methods.

Secondly, I have also noticed that in order to stub some functionality I would need knowledge of the internals of particular objects, which is not very helpful!

Sep 30, 2009 at 12:43 AM

That seems like an awful lot of code to mock one function.  Personally I'm not sure that having the static extension class for IRegionManager is the best design in terms of testability.  Ideally if I want to test that something adds a view to a region I should be able to do

var regionManager = _mocks.DynamicMock<IRegionManager>();
regionManager.AddToRegion(RegionName.MainRegion, _mockView);

If all I want to do is test that the correct method is called in the regionManager with the correct arguments when the command is executed.  I shouldn't have to write any more test code than that.


Sep 30, 2009 at 1:58 AM

This was really tricky but this is what it took to test this with Rhino mocks:

    public void Setup() {
      _mocks = new MockRepository();
      _priceUpdateView = _mocks.Stub<IPriceUpdateView>();
      _serviceLocator = _mocks.Stub<IServiceLocator>();
      _serviceLocator.Stub(c => c.GetInstance(typeof(IPriceUpdateView))).Return(_priceUpdateView);
      ServiceLocator.SetLocatorProvider(() => _serviceLocator);
      _controller = new TDMenuController(StubRegionManager());

    private IRegionManager StubRegionManager() {
      _regionManager = _mocks.Stub<IRegionManager>();
      var regionCollection = _mocks.Stub<IRegionCollection>();
      _region = _mocks.Stub<IRegion>();
      _regionManager.Stub(m => m.Regions).Return(regionCollection);
      regionCollection.Stub(m => m.ContainsRegionWithName(RegionNames.MainRegion)).Return(true);
      regionCollection.Stub(c => c[RegionNames.MainRegion]).Return(_region);
      return _regionManager;

    public void ShowPriceUpdateCommandInvokesPriceUpdateView() {

I really don't like this, but at least I can test all the other commands with another 4 line test.  There is probably a better way to do this (I hope!) I am not a Rhino mocks expert by any means.  I sorta wish CAL had used a mocking framework instead of hand coded mocks as I think then the design would be more geared towards that style of test writing.

One other option would be to import the CAL test libraries and use the mocks from that.  That is actually a decent option and I may consider doing that.


Sep 30, 2009 at 5:29 PM

Ok sorry, one more shot.  I realized I wasn't using the AAA syntax correctly which is described here.  Doing so has reduced the verbosity of the tests further:

    public void Setup() {
      _priceUpdateView = MockRepository.GenerateStub<IPriceUpdateView>();
      _serviceLocator = MockRepository.GenerateStub<IServiceLocator>();
      _serviceLocator.Stub(c => c.GetInstance(typeof(IPriceUpdateView))).Return(_priceUpdateView);
      ServiceLocator.SetLocatorProvider(() => _serviceLocator);
      _controller = new TDMenuController(ArrangeRegionManager());

    private IRegionManager ArrangeRegionManager() {
      _regionManager = MockRepository.GenerateStub<IRegionManager>();
      _regionCollection = MockRepository.GenerateStub<IRegionCollection>();
      _region = MockRepository.GenerateMock<IRegion>();
      _regionManager.Stub(m => m.Regions).Return(_regionCollection);
      _regionCollection.Stub(m => m.ContainsRegionWithName(RegionNames.MainRegion)).Return(true);
      _regionCollection.Stub(c => c[RegionNames.MainRegion]).Return(_region);
      return _regionManager;

    public void ShowPriceUpdateCommandInvokesPriceUpdateView() {
      _region.Expect(r => r.Add(_priceUpdateView)).Return(_regionManager);

Much cleaner.  I can now test that all my menu commands add the correct view to the MainRegion using only three lines and the setup isn't all that bad really and could be extracted to a base class for all similar tests.