- csUnit is now based on .NET 3.5 SP 1
- Parameterized testing moved out of experimental
- Basic support for Microsoft unit testing.
- Several bug fixes.
- csUnit (no surprise!)
- NUnit 2.4.7 (.NET 2.0)
- Microsoft Unit Testing (basic support)
Comments, how-to's, examples, tools, techniques and other material regarding .NET and related technologies.
// _statusMessage is a System.Windows.Controls.TextBlock object
// _statusMessageTime is a System.Threading.Timer object
private void DisplayStatusMessage(string message) {
_statusMessage.Text = message;
_statusMessageTimer = new Timer(ResetStatusMessageCallback,
/* params left out for brevity */);
}
private void ResetStatusMessageCallback(object stateInfo) {
_statusMessage.Text = "";
}
When the timer fires the callback is executed on a thread different to the user interface thread. The UI will not update. In my installation the Silverlight interface would then simply disappear! To fix this you need a way to execute the actual update on the user interface thread. One way is to use the Dispatcher object (Namespace: System.Windows.Threading) of the XAML page. Then the code of the callback implementation looks as follows: private void ResetStatusMessageCallback(object stateInfo) {
Dispatcher.BeginInvoke(() => {
_statusMessage.Text = "";
});
}
Another solution would be to use the DispatcherTimer. I spare you the details but you can check here for an example.
public class Result { public long Status { get; set; } } public class Foo { }Given this starting point you may want to write the following unit test to ensure that class Foo requires a method 'Result NewMethod()':
[TestMethod] public void TestNewMethod() { var foo = new Foo(); var result = foo.NewMethod(); Assert.AreEqual(0, result.Status); }As you type you will notice that when you have typed the dot after 'result' you will not be offered the member list of Result. It's not possible to implicitly type the variable 'result' since the method 'NewMethod()' doesn't exist yet. As a result writing tests in a TDD approach is slowed down when using 'var' instead of explicit types. Here is another view you may take: Writing tests for 'NewMethod()' should include all specifications, including the type of the return value. If you agree with that view you may want to avoid using 'var' in your unit tests. This certainly doesn't apply to people who create their unit tests after the method has been added to the class. I personally wouldn't call this test-first development, let alone test-driven development (or test-driven design as some people argue). Bottom line it depends on where you are coming from. 'var' might not always be the best choice even if it is a new 'cool' feature in C# 3.0.
using System.Runtime.Serialization; namespace AgileTraxx.Services { [DataContract] public class ServiceResult { public ServiceResult(string message, long incidentId) { Message = message; IncidentId = incidentId; } [DataMember] public string Message { get; set; } [DataMember] public long IncidentId { get; set; } } }This class would just take the incident id plus a message. The message could contain information about how to contact support and to note down the incident id. As you can see there is a lot to consider when designing a service interface, including security related factors.
internal class WorkItem {
public WorkItem () {
}
public virtual long Id {
get {
return _id;
}
set {
_id = value;
}
}
public virtual string Title {
get {
return _title;
}
set {
_title = Validation.EnsureNonEmptyString(value, "Title");
}
}
private long _id;
private string _title = "";
}
I left most of it out. For now let's look at just the id and the title since those two demonstrate sufficiently the issue.
What you will notice is that the setter for the title contains validation code ("Validation.EnsureNonEmptyString(...)").
The problem starts when you query for one or more WorkItem's. Then NHibernate will use the property setters to initialize the instance of WorkItem. For strings the default value is null (nothing in VB.NET). With the given code, however, the validation will throw an exception since that is what it is designed to do. It doesn't care whether the setter is called by NHibernate or anything else.
So next I tried to figure out what alternatives I would have for validation and I found NHibernate.Validator. Although a step in the right direction I didn't like that the client code for the domain objects would have to explicitly call the validation. Alternatively the validation would have to be invoke via the event call backs from NHibernate. In both cases the domain class would only work properly if something else would collaborate. I didn't like that concept and started to look for an alternative.
And there is a quite simple solution to this: Change the configuration for NHibernate so that it doesn't use the properties to initialize the domain objects. This configuration change can be done via Fluent NHibernate as follows:
_hibernateConfig = new Configuration();
AutoPersistenceModel persistenceModel =
AutoPersistenceModel
.MapEntitiesFromAssemblyOf()
.Where(TypeIsIncluded)
.ForTypesThatDeriveFrom(
map => map
.DefaultAccess
.AsCamelCaseField(Prefix.Underscore));
persistenceModel.Configure(_hibernateConfig);
Depending on your naming conventions you may want to use a different access strategy or a different Prefix value. In my case it was Camel Casing with an underscore as a prefix.
After I finally found this solution I was able to keep the domain classes squeaky clean and at the same time stay with using the Fluent NHibernate interface and avoiding exception during the initialization of instances of domain classes.
Of course I'm not sure whether this is the only and/or best option. If you have other options that are even better, please drop me a note. I'm always keen to learn more!