Stub or Expect, AssertWasCalled or VerifyAllExceptions

Regarding the following unit-test principles, I think Stub + AsserWasCalled is better.

  • Each test should only test one thing,
  • All setup code should be in one place,
  • Test behavior not method.

using System.Collections.Generic;
using NUnit.Framework;
using Rhino.Mocks;

namespace Demo
{
    public interface IDependencyA {IEnumerable<string> GetList();}

    public interface IDependencyB {string DoSth(IEnumerable<string> input);}

    public interface IDependencyC {string DoSthElse(string input);}

    public class SystemToTest
    {
        private readonly IDependencyA _a;
        private readonly IDependencyB _b;
        private readonly IDependencyC _c;

        public SystemToTest(IDependencyA a, IDependencyB b, IDependencyC c)
        {
            _a = a;
            _b = b;
            _c = c;
        }

        public string Action()
        {
            return _c.DoSthElse(_b.DoSth(_a.GetList()));
        }
    }

    [TestFixture]
    public class MockDemo
    {
        protected IDependencyA _mockDependencyA;
        protected IDependencyB _mockDependencyB;
        protected IDependencyC _mockDependencyC;

        private SystemToTest _systemUnderTest;

        [SetUp]
        public virtual void Setup()
        {
            _mockDependencyA = MockRepository.GenerateMock<IDependencyA>();
            _mockDependencyB = MockRepository.GenerateMock<IDependencyB>();
            _mockDependencyC = MockRepository.GenerateMock<IDependencyC>();

            _systemUnderTest = new SystemToTest(_mockDependencyA,
                                                _mockDependencyB,
                                                _mockDependencyC);

            // If B.DoSth can NOT run with null input, this stub is needed.
            _mockDependencyA.Stub(x => x.GetList()).Return(
                new List<string>()
                );
        }

        [TestFixture]
        public class When_Action_happens : MockDemo
        {
            [SetUp]
            public override void Setup()
            {
                base.Setup();
                _systemUnderTest.Action();
            }

            [Test]
            public void should_ask_a_to_get_list()
            {
                 _mockDependencyA.AssertWasCalled(x => x.GetList());
                // Can also run _mockRequestRepository.VerifyAllExpectations();
                //  if using Expect in Setup instead of Stub
            }

            [Test]
            public void should_ask_b_to_do_sth()
            {

                _mockDependencyB.AssertWasCalled(
                    x => x.DoSth(null),
                    opt => opt.IgnoreArguments());
            }

            [Test]
            public void should_ask_c_to_do_sth_else()
            {
                _mockDependencyC.AssertWasCalled(
                    x => x.DoSthElse(null),
                    opt => opt.IgnoreArguments());
            }
        }
    }
}

Advertisements

A Rhino Bug: Stub property back to default

Somebody meationed this on Rhino group, I actually got the same problem, but I didn’t realize it’s caused by setting another property which happens in my eventhandler.

Ayende said he already fixed this problem, but how come I still get it? Even tried the latest one from the downloaded page. So I had to try my first svn checkout. Everything went smoothly, unless a little bit diffifcult in setting proxy, because I’m behind a firewall. Tortoise svn can’t read this info from IE.

Before svn ready, I tried downloading the tarball, nant didn’t work, at lease not completely success, because AssemblyInfo.cs gegeranted failure due to the absence of _revision.xml. Result is, the Rhino.Mock.dll I build has not version number.

After my svn proxy setting done, I did a new checkout, command line nant, then got this newly official-released-like dll: Assembly version : 3.5.0.1337, File/Product version: 3.5.0.1960. (What’s the real meaning of those kinds of versions? Why they are different?)

Any finally, my test based on stub passed. It was a problem when using RhinoMocks 3.5.0.2, file version: 3.5.0.0. I think I got that version from 3.5RC, the stupid thing of mine is, my project reference is pointing to somewhere wrong, then all my later updates didn’t reach it unitl now.

Should always ignoreArgument when AssertWasCalled

I should have added this option in my test earlier, then I won’t waste 2+ hours today. The reason causing problem was very simple, AssertWasCalled() method in current verion RhinoMocks (3.5.0.1337 RC) doesn’t action consistently. I think it’s because comparing the object reference equalty. I had to add options=>options.IgnoreArguments() to get around from this.

Here is a piece of my MVP + CLSA test. Struggled for a while with Property setter, thanks God, it isn’t that hard.


    [TestFixture]
    public class When_initializing_view : EstablishContext
    {
        [Test]
        public void should_call_view_setter_if_id_exists()
        {
            // Arrange
            _mockOrganizationRepository.Expect(x => x.FindById(1)).Return(_stubOrganizationDTO);

            _mockView = MockRepository.GenerateMock<IEditDetailsView<OrganizationBO>>();

            _presenter = new EditDetailsPresenter<OrganizationBO>(_mockView);

            // Action
            _presenter.InitViewFor(1);

            // Assert
            _mockView.AssertWasCalled(x => x.CurrentBO = null,
                options =>options.IgnoreArguments() );
        }
    }

I then created a generic EditDetailsPresenter, worked as I expected with one concern left: How to mock DataPortal directly. Currently I am still mocking repository. Ideally I should mock DataPortal instead, otherwise I have to make sure there is at least one BO is fully functional.

Mocking DataPortal is very hard, because those Fecth, Create, Update and Delete are all static methods, I had to create an adapter to wrap those static methods, then using StructreMap again inside adapter enable switching between DataPortal and mock DomainDAO, here is what I have tried:

  1. Create DomainDAO and IDomainDAO,
    public class DomainDAO<BO> : IDomainDAO<BO>
    {
    public BO Fetch(object criteria)
    {
    return DataPortal.Fetch<BO>(criteria);
    }
    
    public BO Create()
    {
    return DataPortal.Create<BO>();
    }
    
    public BO Update(BO bo)
    {
    return DataPortal.Update<BO>(bo);
    }
    
    public void Delete(object criteria)
    {
    DataPortal.Delete<BO>(criteria);
    }
    }
    
    public interface IDomainDAO<T>
    {
    T Fetch(object criteria);
    T Create();
    T Update(T bo);
    void Delete(object criteria);
    }
    
    
  2. Create DAOManager to Get DomainDAO:
    public static class DAOManager
    {
    public static IDomainDAO<BO> DomainDAO<BO>()
    {
    return ObjectFactory.GetInstance<IDomainDAO<BO>>();
    }
    }
    
    
  3. Change classic factory method in BO from DataPortal to this new DAOManager.
    public static OrganizationBO GetOrganizationBO(int stakeholderId)
    {
    return DAOManager.DomainDAO<OrganizationBO>().Fetch(new SingleCriteria<OrganizationBO, int>(stakeholderId));
    //            return DataPortal.Fetch<OrganizationBO>(new SingleCriteria<OrganizationBO, int>(stakeholderId));
    }
    
  4. The presenter testing code can be changed to:
    
    [SetUp]
    public void SetUp()
    {
    _mockService = MockRepository.GenerateMock<IDomainDAO<OrganizationBO>>();
    ObjectFactory.Inject<IDomainDAO<OrganizationBO>>(_mockService);
    }
    
    [TearDown]
    public void TearDown()
    {
    ObjectFactory.ResetDefaults();
    }
    
    [TestFixture]
    public class When_initializing_view : EstablishContext
    {
            [Test]
            public void should_call_view_setter_if_id_exists()
            {
                // Arrange
                // We don't need to set return value here.
                _mockService.Expect(x => x.Fetch(new SingleCriteria<OrganizationBO, int>(68190)));
    
                _mockView = MockRepository.GenerateMock<IEditDetailsView<OrganizationBO>>();
    
                _presenter = new EditDetailsPresenter<OrganizationBO>(_mockView);
    
                // Action
                _presenter.InitViewFor(68190);
    
                // Assert
                _mockView.AssertWasCalled(x => x.CurrentBO = null,
                    options => options.IgnoreArguments() );
            }
    
            [Test]
            public void should_set_error_msg_in_view_if_id_not_exists()
            {
                // Arrange
                Exception ex = new Exception("Data Not Found", new DataNotFoundException());
                _mockService.Expect(x => x.Fetch(new SingleCriteria<OrganizationBO, int>(1)))
                    .IgnoreArguments()
                    .Throw(new DataPortalException("DataPortal.Fetch failed.",
                        ex,
                        null)); // See, we don't have to mock BO here, unless you try to read BO through exception in UI.
    
                _mockView = MockRepository.GenerateMock<IEditDetailsView<OrganizationBO>>();
    
                _presenter = new EditDetailsPresenter<OrganizationBO>(_mockView);
    
                // Action
                _presenter.InitViewFor(1);
    
                // Assert
                _mockView.AssertWasCalled(x => x.ShowError(null),
                    options => options.IgnoreArguments() );
            }
    

Fetch can be done this way, but I can’t mock Save() because it’s deep in Csla, unless I can override BusinessBase.Save() which is another mission impossible (too many internal classes involved). To make Csla TDD friendly, let ask for TypeMock to save us out.

 [TestFixture]
    public class When_view_firing_save_event : EstablishContext
    {
        [Test]
        public void should_set_success_msg_and_set_new_BO_in_view_if_save_new_bo_succeed()
        {
            // Arrange
            OrganizationBO orgBo = DataPortal.Create<OrganizationBO>();
            orgBo.Name = "test Org";
            Assert.That(orgBo.IsValid, orgBo.GetValidationMessage());

            _mockView = MockRepository.GenerateMock<IEditDetailsView<OrganizationBO>>();
            _mockView.Stub(x => x.CurrentBO).Return(orgBo).Repeat.Any();

            _presenter = new EditDetailsPresenter<OrganizationBO>(_mockView);

            // This won't work, because BusinessBase.Save() is tightly coupled to DataPortal.
            //_mockService.Expect(x => x.Update(orgBo)).IgnoreArguments();

            // Use TypeMock to mock DataPortal.Update() inside BusinessBase.Save()
            using (RecordExpectations recorder = RecorderManager.StartRecording())
            {
                  // CAUTION: ALL calls here are mocked!!!
                  recorder.DefaultBehavior.IgnoreArguments();
                  recorder.ExpectAndReturn(DataPortal.Update(orgBo), orgBo);
            }

            // Action
            _mockView.Raise(x => x.RequestSave += null, this, EventArgs.Empty);

            // Assert
            _mockView.AssertWasCalled(x => x.CurrentBO = null,
                                      options => options.IgnoreArguments());

            _mockView.AssertWasCalled(x => x.ShowMessage(null),
                                      options => options.IgnoreArguments());

    }

We can remove DomainDAO then if using TypeMock to mock DataPortal.

The new ObjectFactory in CSLA 3.6 seems can make this mock easier, looks like your own ObjectFactory is not static class anymore, different than DataPortal. By creating your own IDataPortal or IObjectFactory, as Ryan did,  mocking those service layer objects should become possible. Someday I will look into this CSLA.ObjectFactory thing if we aren’t going to TypeMock. Rocky’s statement indicates this will be a lot of work:

It is very important to realize that when using this factory model, the data portal does virtually nothing for you. It doesn’t automatically call MarkOld(), MarkNew() or MarkAsChild(). You assume total responsibility for creating and initializing the business object graph, and for setting the state of all objects in the graph.

But it seems Ryan’s ObjectFactroy sample code already finished most of them. One thing doesn’t fit our situation is, we need IRepository<> changed to IDomainObjectRepository in Factory.


        private readonly IRepository<T> _repository;
        public BusinessBaseServerFactory(IRepository<T> repository)
        {
            _repository = repository;
        }

So far, I think unless CSLA.ObjectFactory can provide an optional attribute something like “RepositoryType”, I have to create One ObjectFacotry per BO. Our libaray will become more messier.

Seperate concern between parent and child

Do we need to separate concern between parent object and its child? Say we have a stakeholder BO, which can have multiple email BOs, (an email BO collection). Then where should we place those specs/unit-tests for email BO?

Because emailBO is a child BO, the normal way to save it should be only through stakeholderBO.Save(). It’s possible that stakeholderBO might still be work-in-progress, or having problem caused by other childBO, e.g., telephoneBO. Or more likely, it’s not finish yet. Can we still work on EmailBO without worry too much about it’s parent – StakeholderBO?

So seperate concern is necessary. We need an interface to implement design-by-contract.

Create an IStakeholder interface, mock it in emailBO unit-test. (Thanks to Rhino, we don’t need worry about data portal any more. ) But we need to explicitly call SetParent() in emailBOCollection to simulate the LoadProperty behavior in stakeholderBO.

The test code:


            // Arrange
            var emailRepository = MockRepository.GenerateMock<IEmailRepository>();
            ObjectFactory.Inject<IEmailRepository>(emailRepository);

            EmailDTO OneValidTestDTO = new EmailDTO()
                                           {
                                               Address = "2@d.c", EmailRole = "Home",
                                               StakeholderId = 123, StakeholderEmailId = 456
                                           };

            emailRepository.Expect(x => x.Insert(null)).IgnoreArguments().Return(OneValidTestDTO);
            // or play the new inline constraints syntax
            emailRepository.Expect(x => x.Insert(Arg<EmailDTO>.Is.Anything)).Return(OneValidTestDTO); 

            IStakeholder mockStakeholderBO = MockRepository.GenerateMock<IStakeholder>();  

            // Action
            EmailBOCollection emails = EmailBOCollection.NewEmailBOCollection();

            // SetStakeholder is created in EmailBOCollection to call private SetParent through reflection.
            // This is optional because the second parm in DataPortal.UpdateChild() will be passed
            // to child_XYZ() as the parameter which is the real parent.
            // emails.SetStakeholder(mockStakeholderBO);   // IStakeholder should extend csla.IParent.

            var newEmail = emails.AddNew();
            // Make this new EmailBO valid.
            newEmail.Address = "1@dc.com";
            newEmail.EmailRole = "Home";

            Assert.That(emails[0].BrokenRulesCollection, Is.Empty, emails[0].BrokenRulesCollection.ToString());

            // this is to simulate the parent.Save() in the real world,
            DataPortal.UpdateChild(emails, mockStakeholderBO);
            // We don't want and can't call stakeholder.Save() here

            // Assert
            Assert.That(emails[0].StakeholderEmailId == OneValidTestDTO.StakeholderEmailId);
            Assert.That(emails[0].StakeholderId == OneValidTestDTO.StakeholderId);  

            // Reset to default
            ObjectFactory.ResetDefaults();

Unfortunately, SetParent(IParent) is a private method in IEditableObject and IEditableCollection. I had to create a public wrapper in my base class.


        public void SetStakeholder(IParent parent)
        {
            object[] parm = new object[] { parent };

            var method = this.GetType().GetMethod("Csla.Core.IEditableCollection.SetParent", BindingFlags.Instance | BindingFlags.NonPublic);

            method.Invoke(this, parm);
        }

But, later I figured out it’s not necessary, only if I am doing some parent-related validation in emailBO, say, an Organization type stakeholder can not have home email role.

Dataportal.Update() method is key to simulate parent.Save(), this old (3.0) syntax works great in my mock/TDD solution to CSLA.

Repository pattern in CSLA

We use Repository Pattern inside our CSLA BO to extract data access code into a separate class – repository object,  because we use interface IRepository to loose couple BO and concrete Repository object and implement “design by contract”, so BO doesn’t care which technology repository is using, either using ADO.net or Linq to SQL, or NHinbernate or Entity Framework .

The benefits of using this model include:

  • Loose coupling between BL and DAL
  • Easy to switch to different Data Access technology
  • Central place to control and switch IOC container

Updated at Feb. 09, 2009:
Found this post about the difference between DAO and Repository pattern. Yes, my model is more similar to DAO, because I was following one Repo/DAO per table rule. In fact, I’m on the progress of switching to the new Csla.ObjectFactory which is a real repository class, or, at lease, can be a repository wrapper, as Ryan did in his example.

Using StructureMap to mock DataAccess in CSLA BO

I had always thought StructureMap is just another IOC tool similar to Castle windsor, until yesterday I read Karl Seguin’s Foundations of Programming, Chapter 4, I was shocked immediately by the injectStub method provided by StructureMap, which is now renamed to inject(). I think this explicitly injection is better than TypeMock implicitly mock instance object.

For example, I have an Organization BO,


public static OrganizationBO GetOrganizationBO(int Id)
{
return DataPortal.Fetch<OrganizationBO>(new SingleCriteria<OrganizationBO, int>(Id));
}

private void DataPortal_Fetch(SingleCriteria<OrganizationBO, int> criteria)
{
OrganizationDTO data = DataAccess.OrganizationRepository().FindById(criteria.Value);

if (data != null)
{
LoadFromDTO(data);
}
}

The repository is declared in DataAccess class to centralize all the dataaccess coupling inside CALS BOs.


public static IRepository<OrganizationDTO> OrganizationRepository()
{

// instead of direct coupling return new OrganizationRepository();
// I use StrcutureMap
return ObjectFactory.GetInstance<IRepository<OrganizationDTO>>();
}

The content of IOC config file:

<DefaultInstance
PluginType=”DemoApp.Data.Interfaces.IRepository`1,DemoApp.Data”    PluggedType=”DemoApp.Data.Repository.OrganizationRepository,DemoApp.Data”
/>

We can also use other different ways to set dependency, like setDefault in code, or search assembly at  runtime as shown in this post.

Test  code:


[Test]
public void CanGetFromInjectedMockRepository()
{
var mockRepository = new Moq.Mock<IRepository<OrganizationDTO>>();

// Id in MoQ matters. But TypeMock doesn't care.
mockRepository.Expect(x => x.FindById(8172)).Returns(
new OrganizationDTO
{
Id = 1,
Name = "A test org name"
});

ObjectFactory.Inject(typeof(IRepository<OrganizationDTO>), mockRepository.Object);

var o = OrganizationBO.GetOrganizationBO(8172);

Assert.AreEqual(1, o.Id);
Assert.AreEqual("A test org name", o.Name);
}

Here is an artile introducing StructureMap, as it mentioned, StrucutreMap is very good choice if you are working on a class has no “constructor injection”, CSLA is one of those!

I have the same feeling, as the author Karl Seguin said, constructor injection doesn’t really solve the extensibility problem; how does someone add(try to replace) a new plug-in without recompiling the entire application?

The problem/drawback to DI is also obvious, the xml config file keeps growing and expanding. The performance and mantiance will become an issue. That’s why Boo was inverted to save / speed up Castle Windsor. But what about structure Map?

Also I need tool / method to test this xml config file, see details here and here. Unfortunately, I couldn’t make this <structuremap.verification> task loaded into NAnt, (maybe this doesn’t exist in those two dlls at all? I can’t tell because NAnt loadTask doesn’t have output). I tried to different folders and also “Forced scan” using <loadtasks> command, neither one works. Thanks God, Jeremy does have another way to test config file,so called smock test:

ObjectFactory.AssertConfigurationIsValid();

Regarding unit-test and mock, I spent a lot time trying to figure out how to reset the default back. It turns out the documented ObjectFactory.resetdefault has been changed to reset.

Create multiple criteria to mock DataAcess in CSLABO

I posted before about using TypeMock to do mock data access in CSLABO. Today I am posting another way to mock dataaccess without using TypeMock.

First, I need to create IRepository<DTO> interface:

public interface IRepository<DTO>
{
DTO FindById(int id);
DTO Insert(DTO data);
void Update(DTO newData, DTO oldData);
void Delete(DTO data);
void DeleteById(int id);

Second, create my OrganizationRepository by implementing this IRepository<OrgarnizationDTO>.

Third, in my BO, add those 2 fetch methods:

private void DataPortal_Fetch(SingleCriteria<OrganizationBO, int> criteria)
{
DataPortal_Fetch(new RepositoryCriteria<OrganizationDTO>(new OrganizationRepository(), criteria));
}

private void DataPortal_Fetch(RepositoryCriteria<OrganizationDTO> repositoryCriteria)
{
var data = repositoryCriteria.Repository.FindById(
((SingleCriteria<OrganizationBO, int>)repositoryCriteria.Criteria).Value );

if (data != OrganizationDTO.NULL)
{
LoadFromDTO(data);
}
}

public class RepositoryCriteria<DTO>
{
public IRepository<DTO> Repository;
public CriteriaBase Criteria;

public RepositoryCriteria(IRepository<DTO> repository, CriteriaBase criteria)
{
Criteria = criteria;
Repository = repository;
}
}

Finally, The test code:

[Test]
public void CanFetchFromMoQRepository()
{
var mockRepository = new Moq.Mock<IRepository<OrganizationDTO>>();

// Id in MoQ matters. TypeMock doesn’t.
mockRepository.Expect(x => x.FindById(8172)).Returns(
new OrganizationDTO
{
Id = 1,
Name = “A test org name”
});

var o = DataPortal.Fetch<OrganizationBO>(
new RepositoryCriteria<OrganizationDTO>(
mockRepository.Object,
new SingleCriteria<OrganizationBO, int>(8172)
)
);

Assert.AreEqual(1, o.Id);
Assert.AreEqual(“A test org name”, o.Name);
}

The benefit of this solution is we are a little bit close to loose coupling, but later I figured out it’s still very hard to mock the Save() method. Had to back to TypeMock.