It's been a while since I posted anything here - I've moved jobs recently so the last few months have been taken up with settling into the new role.
I've been thinking a lot about test-driven development recently and whether it's always the best approach, or if there are variations on it that are better suited to some applications. When I first started using TDD I was writing software to run risk and cost-benefit models, which were generally perfect for a test-driven approach. The calculation could be broken down in sub-calculations, each of which would be implemented by a single method, with related calculations grouped into classes. Each sub-calculation could then be unit tested and whole thing usually worked out beautifully. They were almost textbook cases of when to employ TDD.
Recently I've been developing much more standard line-of-business applications, heavy on CRUD, with a small amount of complex business logic, and doing TDD just feels like going through the motions, with little benefit gained from it.
What I've decided to do is start researching behaviour-driven development (BDD) as I think it will be better suited to the kind of systems I'm developing now. Plus it will be fun to learn something new!
My companion on this adventure is the Manning book BDD In Action, which I'll be reading on my commute to and from work. I'm also going to document my progress right here! It will be an opportunity to order some of my thoughts, plus a great way to measure my progress.
Watch this space for the first instalment!!
My thoughts on unit testing and coding in general. Mainly C#.NET, but other bits and pieces as well.
Thursday, 10 November 2016
Thursday, 4 February 2016
Creating WCF Client Channels from Configuration
I'm going to write today about WCF: specifically about how to create client channel instances when your config is held somewhere other than the app.config or web.config file of your application. I should point out that I'm not a huge WCF fan, and try not to use it where possible, but sometimes you have no choice.
I've recently been working on a project where some parts of the application don't have access to the web.config file, so their configuration had to be held in a database (there are very good reasons for this, but I won't go into them).
So rather than have the client config in the web.config file and use the generated client proxy classes to make calls to the service, the solution I used was to use the ConfigurationChannelFactory<T> class provided in the System.ServiceModel.Configuration namespace. I created a WcfConfiguration class (more on this later) and used it to create the channel factory as follows:
The ConfigurationChannelFactory<T> object needs various configuration in the form of a System.Configuration.Configuration object, and also some endpoint configuration information. One big restriction of the System.Configuration.Configuration class is that, AFAIK, it can only be instantiated from a config file on the file system. So what I did was take the <system.serviceModel> configuration section that was stored in the database as a string and write this out to a file, to then be used to create the Configuration object. A bit roundabout but there you go!!
The System.Configuration.Configuration object can now be used to create an instance of my WcfConfiguration class, which is just a data bucket for the objects it's given:
The ConfigurationChannelFactory<T> is created as shown above and cached. The cached object is used to create any channels that are needed. This means that, although it's a pain having to write out a physical config file, at least it only needs to be done once.
If anyone has a better solution to this problem, or ideas on how this can be improved, then please let me know!
I've recently been working on a project where some parts of the application don't have access to the web.config file, so their configuration had to be held in a database (there are very good reasons for this, but I won't go into them).
So rather than have the client config in the web.config file and use the generated client proxy classes to make calls to the service, the solution I used was to use the ConfigurationChannelFactory<T> class provided in the System.ServiceModel.Configuration namespace. I created a WcfConfiguration class (more on this later) and used it to create the channel factory as follows:
private static ConfigurationChannelFactory<TChannel> CreateChannelFactory(WcfConfiguration wcfConfiguration) { return new ConfigurationChannelFactory<TChannel>( wcfConfiguration.EndpointConfiguration.Name, wcfConfiguration.Config, new EndpointAddress(wcfConfiguration.EndpointConfiguration.Address)); }
The ConfigurationChannelFactory<T> object needs various configuration in the form of a System.Configuration.Configuration object, and also some endpoint configuration information. One big restriction of the System.Configuration.Configuration class is that, AFAIK, it can only be instantiated from a config file on the file system. So what I did was take the <system.serviceModel> configuration section that was stored in the database as a string and write this out to a file, to then be used to create the Configuration object. A bit roundabout but there you go!!
private System.Configuration.Configuration CreateTempConfigFile(string filename, string rawConfig) { var configFilename = $"{filename}.config"; var configFilepath = Path.Combine(_configDirectory, configFilename); File.WriteAllText(configFilepath, string.Format(ConfigFormat, rawConfig)); var virtualDirectoryMapping = new VirtualDirectoryMapping(_configDirectory, false, configFilename); var fileMap = new WebConfigurationFileMap(); fileMap.VirtualDirectories.Add(VirtualDirectoryName, virtualDirectoryMapping); var webSiteName = HostingEnvironment.SiteName; var configuration = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, VirtualDirectoryName, webSiteName); return configuration; }
The System.Configuration.Configuration object can now be used to create an instance of my WcfConfiguration class, which is just a data bucket for the objects it's given:
private WcfConfiguration CreateWcfConfiguration(System.Configuration.Configuration configuration, string rawConfig) { var serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(configuration); if (serviceModelSectionGroup == null) { throw new System.Configuration.ConfigurationErrorsException("The WCF client configuration does not contain a 'system.serviceModel' section."); } if (serviceModelSectionGroup.Client == null) { throw new System.Configuration.ConfigurationErrorsException("The WCF client configuration does not contain a 'client' section."); } if (serviceModelSectionGroup.Client.Endpoints == null || serviceModelSectionGroup.Client.Endpoints.Count == 0) { throw new System.Configuration.ConfigurationErrorsException("The WCF client configuration does not contain any endpoints in the 'client' section."); } var endpointConfig = serviceModelSectionGroup.Client.Endpoints[0]; var wcfConfiguration = new WcfConfiguration(rawConfig, configuration, endpointConfig) return wcfConfiguration; }
The ConfigurationChannelFactory<T> is created as shown above and cached. The cached object is used to create any channels that are needed. This means that, although it's a pain having to write out a physical config file, at least it only needs to be done once.
If anyone has a better solution to this problem, or ideas on how this can be improved, then please let me know!
Tuesday, 5 January 2016
Testing IoC Containers
Just a quick post now that I'm back from a Christmas break.
One of the tests that I always write in my applications is one to check that my IoC container is configured properly. This is something that is often neglected and I'm not sure why.
It's just as case of writing a test (or tests) to try and resolve every 'entry point' class in your application. For example, in an MVC application you would test that each controller can be resolved. Any dependency that hasn't been registered in the IoC container will then cause a test failure, informing you at compile-time that you have an issue (rather than it rearing its head at runtime).
To take it to the next level of detail you could have a set of tests that verify that each registered depenedency resolves to the correct type, however I've never felt the need to take it this far.
One of the tests that I always write in my applications is one to check that my IoC container is configured properly. This is something that is often neglected and I'm not sure why.
It's just as case of writing a test (or tests) to try and resolve every 'entry point' class in your application. For example, in an MVC application you would test that each controller can be resolved. Any dependency that hasn't been registered in the IoC container will then cause a test failure, informing you at compile-time that you have an issue (rather than it rearing its head at runtime).
To take it to the next level of detail you could have a set of tests that verify that each registered depenedency resolves to the correct type, however I've never felt the need to take it this far.
Subscribe to:
Posts (Atom)