Tuesday, 11 January 2011

A Flush In The Night

Often you want to do some "fix" on your data before pushing it to the database. Typically it's some auditty thingie -- CreatedBy and UpdatedOn kind of stuff. After spreading it all around your application, you finally decide you should keep these things in one place.

If you, like me, is an NHibernate user, most likely you find advice to use a custom IInterceptor or IPreUpdateEventListener. Both are quite ugly solutions, since you have to manipulate the raw state values that are already read from the entity and are ready to be saved to the database. What's even worse, in the latter case you should sync it manually with the entity properties as well. One may think that the original code had been ported from Hibernate before IDictionary was invented (I do understand that there might be some excuses, like performance considerations for example). Find the index of the required field in one array, then fix the value at the corresponding index in another one. Oh joy!

So, it's quite understandable that I wanted a more elegant solution. Just "fix" the entity before being saved, and also do it in a more, well, object oriented fashion. Naturally this should happen just before the property values are read.

So, I put a breakpoint on a property getter and started the debugger. Turned out the property was read by an instance of NHibernate.Event.Default.DefaultFlushEntityEventListener, which leads me to believe that its OnFlushEntity method is what actually turns my properties into arrays of raw values. Further investigation showed that this listener is an element of an array of IFlushEntityEventListener-s. So, my plan (which, unsurprisingly, succeeded), was to put my custom implementation in this array before the default one.

Just show us the code! I hear you say. Ok, ok, I'm coming to that. Suppose you have a base entity class (but you're not quite sure, 'cause there might be some 3rd party entities floating around). You just add a template method to it called EnsureConsistency, or PerformAudit, whatever. Here is my custom listener:

public class CustomFlushEntityEventListener :
IFlushEntityEventListener {
  public void OnFlushEntity(FlushEntityEvent @event) {
   var entity = @event.Entity as EntityBase;
   if (entity != nullentity.EnsureConsistency();
  }
 }
Now you have your class, here is how to tell NHibernate it should use it (during application startup):
configuration.SetListeners(ListenerType.FlushEntity,
 new IFlushEntityEventListener[]
  {
  new CustomFlushEntityEventListener(),
  new DefaultFlushEntityEventListener()
  });

Here "configuration" is an instance of NHibernate.Cfg.Configuration, and the code should be run before you build you SessionFactory. The result is, for each entity being flushed, its EnsureConsistency method is being called. The entity itself knows what to do (if anything) in this case. Audit, denormalization, whatever.

Now I do feel like a real Pro. Please tell me I am.

Update. José F. Romaniello published a response on the nhusers Google group, in which he notes that the aforementioned method is being executed for every damn entity, not just for the changed ones. I need to rewrite the code. It seems like I have to inherit from DefaultFlushEntityEventListener and use its IsUpdateNecessary method in order to update just the changed entities. Thanks José!

Monday, 12 July 2010

Just can't plug this in, baby!

I've just lost about half a day fighting with a stupid StructureMap exception:
StructureMap.Exceptions.StructureMapConfigurationException: StructureMap configuration failures:
Error: 104
Source: Registry: StructureMap.ConfigurationExpression,StructureMap
Type Instance 'bf0f9bf6-304d-4d7b-9cd4-59437e94eb10' (Smart Instance for System.Data.SqlClient.SqlClientFactory) cannot be plugged into type System.Data.Common.DbProviderFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-----------------------------------------------------------------------------------------------------

at StructureMap.Diagnostics.GraphLog.AssertFailures()
at StructureMap.Container.Configure(Action`1 configure)
at StructureMap.ObjectFactory.Configure(Action`1 configure)
My actual code was this:
ObjectFactory.Configure(expr =>
{
expr.For<DbProviderFactory>().Use<SqlClientFactory>();
});


What do you mean by "cannot be plugged in", and why Google can't help me here???

So, a couple of hours later (and with a big help from CThru and Reflector), and I find the StructureMap.Graph.TypeRules.CanBeCast method, which is not just about casting, but says no when, among other things, the concrete type (SqlClientFactory in our case) has no default constructor.

Ok, I can understand. StructureMap doesn't know how to create a concrete instance. How about this:
expr.ForRequestedType<DbProviderFactory>().Use(SqlClientFactory.Instance);
Still no luck:
StructureMap.Exceptions.StructureMapConfigurationException: StructureMap configuration failures:
Error: 104
Source: Registry: StructureMap.ConfigurationExpression,StructureMap
Type Instance '42b890e6-54dc-457e-897a-3e8becc7d0fb' (Object: System.Data.SqlClient.SqlClientFactory) cannot be plugged into type System.Data.Common.DbProviderFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
This is more weird, but a look into the code tells me that we still require the target type to have a default constructor (cause we call the same method). Must be a bug in StructureMap. Too bad, since that would be the most clear and logical solution.

Finally this one worked for me:
expr.ForRequestedType<DbProviderFactory>() .AsSingletons(). TheDefault.Is.ConstructedBy (ctx => SqlClientFactory.Instance);

Have fun!

Monday, 5 July 2010

Testing Asp.Net pages with Telerik's JustMock

It is always nice when a competitor publishes a piece of their code. You can always sneak into the comments and, like, look, I'm better! and put a link to your blog where you show your version proudly, and get a massive following.

Guess what, this is what I'm doing right now commenting on the Mehfuz's post. But the main thing I realized reading his post is that this is the perfect example of how using mocks in certain situations can turn testing into a nightmare. The following is not a problem with JustMock, it's a problem with trying to write a unit test involving a complex framework, and isolating parts of it not meant to be isolated.

(Disclaimer: I do understand that the purpose of the original post is not to teach us how to test Asp.Net pages, but to demonstrate the capabilities of JustMock. So, my intent is not to prove that the author is wrong, but rather to take his example as a perfect situation where mock should absolutely not be used.)

So, in order to write the test, we have to
  1. Mock the HttpBrowserCapabilities class and stub a couple of its properties so that it returns something when needed.
  2. Mock the HttpRequest class (of course) and make the mock return our mocked Browser.
  3. Mock the HttpResponse class as well.
  4. Mock the HttpContext class and stub its Request and Response properties (make the getters return our mock instances).
  5. Finally, we are stubbing the Page.RenderControl method, and it's unclear whether we do it to avoid exceptions, or just for fun.
The main purpose is to test whether the Page instance fires all (well, just some) its lifecycle events, and it's done not using mocks but rather adding event handlers (since we already have our Page instance).

Why do we have to mock all these classes? Why do we have to fire up Reflector and dig into the Framework source in order to make our test pass? Because we have this idea that unit testing means testing a particular class in isolation. Somehow all calculator examples left us with an idea that "unit" == "class".

Now, let's back off a bit and consider this: we are testing a high-level ProcessRequest method, which does a lot of lower-level calls to various classes, which are tightly coupled with each other. So, I think it's logical to say that our "unit" is a good part of the System.Web assembly. With that assumption, everything becomes simple: we don't test just our Page instance, we test the whole unit. Assuming we are the developers of the framework, we can also test the lower level methods which have less dependencies, so that we can mock them more easily.

Back to our integration test, here's what it looks like when we use Ivonna. I have omitted all asserts for clarity; instead, we just write messages to the console, as we would in an exploratory test:
[Test]
public void TestingPageEvents()
{
 var session = new TestSession();
 var request = new WebRequest("Default.aspx");
 request.EventHandlers.Page_Init = 
             (sender, e) => Console.WriteLine("Init fired");
 request.EventHandlers.Page_Load = 
             (sender, e) => Console.WriteLine("Load fired");
 session.ProcessRequest(request);
}


This code executes a test against a "real" Web page, with a "real" HttpContext and other necessary objects, so it gives us much more valuable information about the behavior of our system in "real world" situations.

Check out a fresh version of Ivonna here.