|
||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article explains how to unit test an enumeration which maps a table in the database. The concept is simple: how to ensure an enumeration is up-to-date with a table in the database? And why would you want to do that? BackgroundAlmost every project has some sort of enumeration that represents the values in a database table. It might be some sort of order status, a category type etc. If an enumeration is present in both code and the database, this makes room for inconsistency. You might update the database and forget to update the code, or do the opposite, and this can introduce problems. It's all about reducing human errors, and making code consistent and easy to maintain. The earlier you are aware of an issue, the better. Another option is to look into code generation, but that's another article. You can also use this unit test in addition to code generation to make it bullet proof. How does it work?I will not delve into the code behind the validation, but I will explain how it works and how you can make use of this feature. Please download the source code if you are interested about what happens behind the scenes. A custom attribute is put on the enumeration that is to be validated. This attribute describes which table the enumeration corresponds to. A unit test runs the validation, and all enumerations are fetched by using reflection. An enumeration is mapped to a list of fields of type
Using the codeIn order to validate an enum, we can't really hardcode it. The trick is to use an attribute and tag the enumerations. using EnumValidation;
[ValidateEnum()]
public enum Season
{
Winter = 1,
Spring,
Summer,
Autumn
}
If the table name differs from the enum name, simply supply the table name in the attribute constructor. [ValidateEnum("SeasonType")]
public enum Season
...
Fort mapping a bitwise enumeration, [Flags]
[ValidateEnum()]
public enum Season
{
Winter = 1,
Spring,
Summer,
Autumn,
All = Winter | Spring | Summer | Autumn
//should be 7 in database
}
In some cases, you can't use the name column in the table. It might be used for a description text for a dropdown list etc. In such a case, you should add an extra column that represents the enum field name, e.g., a new column named "EnumFieldName". To map this in the code, add the column name after the table name, like this: [ValidateEnum("Season", "EnumFieldName")]
...
So far, so good. This explains how to set an attribute and include the enumeration in the validation process. Now you need a unit test to trigger the validation. The unit test below will start the validation and hook up on the [TestMethod]
public void ValidateEnums()
{
EnumValidator validator = new EnumValidator(ConnectionString);
validator.Validated += new
EventHandler<EnumValidationEventArgs>(validator_Validated);
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
bool success = validator.Validate(assemblies);
Assert.IsTrue(success, "One or more validations failed," +
" or an error occured. Please look " +
"at the error log for details.");
}
As you see, we hook up the void validator_Validated(object sender, EnumValidationEventArgs e)
{
string message = e.Message;
//p.s. you can get the attribute that was validated
//through the e.Attribute property.
if (!e.Success)
{
Console.WriteLine(message);
if (e.HasException)
{
//This will occur if the validation threw an exception.
//E.g. the table name defined in the attribute was wrong.
//e.g. logX.LogError(message)
}
else
{
//This will occur if the validation failed because
//of mismatch between the database and the code.
//e.g. logX.LogWarning(message)
}
}
}
Let's have a look on some of the properties that can be set on the validation object. Use the validator.Target = Target.Code;
Another option is the validator.IgnoreCase = true;
Getting started
To start using this in your own project, copy and reference the DLL in your project. Make a new unit test, or copy the one supplied in the demo project. Attach some sort of log tool to be notified of errors. You might need to reconsider how to fetch the different DLLs. Well, that's it. Download the demo/source. Try it. Give some feedback. History
|
|||||||||||||||||||||||||||||||||||||||||||||||