2

So, I've been searching around on the internet for a bit, trying to see if someone has already invented the wheel here. What I want to do is write an integration test that will parse the current project, find all references to a certain method, find it's arguments, and then check the database for that argument. For example:

public interface IContentProvider
{
     ContentItem GetContentFor(string descriptor);
}

public class ContentProvider : IContentProvider
{
    public virtual ContentItem GetContentFor(string descriptor)
    {
        // Fetches Content from Database for descriptor and returns in
    }
}

Any other class will get an IContentProvider injected into their constructor using IOC, such that they could write something like:

contentProvider.GetContentFor("SomeDescriptor");
contentProvider.GetContentFor("SomeOtherDescriptor");

Basically, the unit test finds all these references, find the set of text ["SomeDescriptor", "SomeOtherDescriptor"], and then I can check the database to make sure I have rows defined for those descriptors. Furthermore, the descriptors are hard coded.

I could make an enum value for all descriptors, but the enum would have thousands of possible options, and that seems like kinda a hack.

Now, this link on SO: How I can get all reference with Reflection + C# basically says it's impossible without some very advanced IL parsing. To clarify; I don't need Reflector or anything - it's just to be an automated test I can run so that if any other developers on my team check in code that calls for this content without creating the DB record, the test will fail.

Is this possible? If so, does anyone have a resource to look at or sample code to modify?

EDIT: Alternatively, perhaps a different method of doing this VS trying to find all references? The end result is I want a test to fail when the record doesnt exist.

Community
  • 1
  • 1
Tejs
  • 40,736
  • 10
  • 68
  • 86

1 Answers1

1

This will be very difficult: your program may compute the value of the descriptor, which will mean your test is able to know which value are possible without executing said code.

I would suggest to change the way you program here, by using an enum type, or coding using the type safe enum pattern. This way, each and every use of a GetContentFor will be safe: the argument is part of the enum, and the languages type checker performs the check.

Your test can then easily iterate on the different enum fields, and check they are all declared in your database, very easily.

Adding a new content key requires editing the enum, but this is a small inconvenient you can live with, as it help a log ensuring all calls are safe.

tonio
  • 10,355
  • 2
  • 46
  • 60
  • 1
    I agree, this may be the easiest way to go. However, that enum will be HUGE. I guess I could always use CodeSmith and generate the initial enum from the DB... – Tejs Mar 29 '11 at 17:31
  • If the list of keys to use is somehow known at build time (which it is in your case: code directly references the keys), then your could even use the enum as a tool to initialize and maintain the table in the database. For instance, when deploying to a production system, you could have your installer use the enum to update the table in the production db. – tonio Mar 29 '11 at 17:50
  • Unfortunately, I'm refactoring code on top of a legacy DB - I won't be able to deploy from scratch =/ – Tejs Mar 29 '11 at 17:57
  • 1
    Talked it over with the team and we all agree going the enum route is good enough. Marking as answered. – Tejs Mar 29 '11 at 19:59