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.

Advertisements

2 thoughts on “Seperate concern between parent and child

  1. Pingback: Csla.ObjectFactory Part II - Difficulties on Child BO « maonet technotes

  2. Pingback: Video – Reunión ALT .NET Café 29 De Agosto « BeyondNet

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s