Recently my company decided it was time to automate some of the plumbing work, such as the data access layer (thankfully). I checked out a few options (LLBLGen, MyGeneration, CodeSmith and SubSonic) and finally decided on CodeSmith because I had used it before and I felt it was the best fit for the company (in many different areas).
I’m using .NetTiers to create the plumbing code for our applications.
In .NetTiers, Processors are used to add custom business logic into the processing of your data. For example, perhaps you want to make sure that a country only exists ONCE in your system, you could add this functionality here. This thread covers the topic of how to add a a processor to your service layer.
The only problem is that if you want to test your processor using Unit Testing, you are now also testing the data access, database, etc. Its tightly coupled, there’s not an easy way to test this. But in actually, there is. Here’s how:
The problem lies in the ValidateIfCountry method. It has a dependency on the “CountryService”. We cannot mock this out. Its tightly coupled with the Processor. We can eliminate this coupling by injecting a reference to a “CountryService” through constuctor injection. Here’s how. (please refer to this thread for full doc on this class).
Previous Constructor Code (with private members shown):
private Entities.Country _country;
/// <summary>
/// Country Processor
/// </summary>
/// <param name=”country”></param>
public VerifyCountryProcessor(Entities.Country country)
{
this._country = country;
}
New Constructor Code, injecting a CountryService:
private Entities.Country _country;
private CountryServiceBase _serviceBase;
/// <summary>
/// Country Processor
/// </summary>
/// <param name=”country”></param>
public VerifyCountryProcessor(Entities.Country country, CountryServiceBase serviceBase)
{
this._country = country;
this._serviceBase = serviceBase;
}
How to Inject it from the original CountryServiceClass
In the example provided by the .NetTiers team, they said to override the Insert Method with this code, to get the processor to run:
Old Code
public override bool Insert(Order entity)
{
ProcessorList.Add(new VerifyCountryProcessor(entity));
Execute();
return base.Insert(entity);
}
This is is correct, but this time we need to inject a CountryService object into the Processor.
New Code
public override bool Insert(Order entity)
{
ProcessorList.Add(new VerifyCountryProcessor(entity, this));
Execute();
return base.Insert(entity);
}
Since we are already in the “CountryService” class when we’re overriding the Insert Method, and since the CountryService inherits from “CountryServiceBase”, we can inject this reference into the InventoryProcessor through the constuctor. We have now eliminated the tightly coupled reference inside of the processor. We can now test the functionality through unit testing.
How To Test
I utilize Rhino Mocks for my mocking so here’s how to do it with Rhino Mocks.
#region Using Directives
using System;
using System.Collections.Generic;
using System.Text;
using ExampleCompany.App.Entities;
using ExampleCompany.App.Services;
using NUnit.Framework;
using Rhino.Mocks;
using ExampleCompany.App.Services.Pipeline;
#endregion
namespace ExampleCompany.App.UnitTests
{
[TestFixture]
public class CountryProcessorTest
{
#region Test Setup
MockRepository mocks;
CountryService countryService;
[SetUp]
public void SetUp()
{
mocks = new MockRepository();
countryService = mocks.CreateMock<CountryService>();
}
[TearDown]
public void TearDown()
{
mocks.VerifyAll();
}
#endregion
#region Tests
[Test]
public void TestCountryProcessorForDuplicateName()
{
Country country = new Country();
country.Country_Name = “FOO”;
// Needed for a return value
TList<Country> cs = new TList<Country>();
cs.Add(country);
string whereClause = String.Format(“{1} = ‘{0}'”, CountryColumn.Country_Name.ToString(), country.Country_Name);
Expect.Call(countryService.Find(whereClause)).Return(cs);
Country country2 = new Country();
country2.Country_Name = “FOO”;
VerifyCountryProcessor countryProcessor = new VerifyCountryProcessor(countryService, country2);
Expect.Call(countryService.ToString()).Repeat.Any();
mocks.ReplayAll();
IProcessorResult result = countryProcessor.Process();
Assert.AreEqual(false, result.Result);
Assert.AreEqual(“The country FOO already exists and cannot be added or updated.”, result.BrokenRulesLists[typeof(ExampleCompany.App.Entities.Country)][0].Description);
}
#endregion
}
}
Conclusion
By utilizing dependency injection in the processors, we’re able to successfully test the processor utiliting unit testing without having to worry about a database connection at the same time. Very helpful. 🙂
Coach Outlet Online says
 http://www.mycoachoutletstoreonline.com
Coach Factory Online says
Business coaching is an informal, open affair. You will meet with the coach and he will assess your business’s needs, and then tailor his services to your precise requirements.
Coach Factory Outlet says
http://buycoachfactoryoutletsz.com