ploeh blog danish software design
StructureMap PerRequest vs. Unique lifetimes
StructureMap offers several different lifetimes, among these two known as PerRequest and Unique respectively. Recently I found myself wondering what was the difference between those two, but a little help from Jeremy Miller put me on the right track.
In short, Unique is equivalent to what Castle Windsor calls Transient: every time an instance of a type is needed, a new instance is created. Even if we need the same service multiple times in the same resolved graph, multiple instances are created.
PerRequest, on the other hand, is a bit special. Each type can be viewed as a Singleton within a single call to GetInstance, but as Transient across different invocations of GetInstance. In other words, the same instance will be shared within a resolved object graph, but if we resolve the same root type once more, we will get a new shared instance - a Singleton local to that graph.
Here are some unit tests I wrote to verify this behavior (recall that PerRequest is StructureMap's default lifestyle):
[Fact] public void ResolveServicesWithSameUniqueDependency() { var container = new Container(); container.Configure(x => { var unique = new UniquePerRequestLifecycle(); x.For<IIngredient>().LifecycleIs(unique) .Use<Shrimp>(); x.For<OliveOil>().LifecycleIs(unique); x.For<EggYolk>().LifecycleIs(unique); x.For<Vinegar>().LifecycleIs(unique); x.For<IIngredient>().LifecycleIs(unique) .Use<Vinaigrette>(); x.For<IIngredient>().LifecycleIs(unique) .Use<Mayonnaise>(); x.For<Course>().LifecycleIs(unique); }); var c1 = container.GetInstance<Course>(); var c2 = container.GetInstance<Course>(); Assert.NotSame( c1.Ingredients.OfType<Vinaigrette>().Single().Oil, c1.Ingredients.OfType<Mayonnaise>().Single().Oil); Assert.NotSame( c2.Ingredients.OfType<Vinaigrette>().Single().Oil, c2.Ingredients.OfType<Mayonnaise>().Single().Oil); Assert.NotSame( c1.Ingredients.OfType<Vinaigrette>().Single().Oil, c2.Ingredients.OfType<Vinaigrette>().Single().Oil); } [Fact] public void ResolveServicesWithSamePerRequestDependency() { var container = new Container(); container.Configure(x => { x.For<IIngredient>().Use<Shrimp>(); x.For<OliveOil>(); x.For<EggYolk>(); x.For<Vinegar>(); x.For<IIngredient>().Use<Vinaigrette>(); x.For<IIngredient>().Use<Mayonnaise>(); }); var c1 = container.GetInstance<Course>(); var c2 = container.GetInstance<Course>(); Assert.Same( c1.Ingredients.OfType<Vinaigrette>().Single().Oil, c1.Ingredients.OfType<Mayonnaise>().Single().Oil); Assert.Same( c2.Ingredients.OfType<Vinaigrette>().Single().Oil, c2.Ingredients.OfType<Mayonnaise>().Single().Oil); Assert.NotSame( c1.Ingredients.OfType<Vinaigrette>().Single().Oil, c2.Ingredients.OfType<Vinaigrette>().Single().Oil); }
Notice that in both cases, the OliveOil instances are different across two independently resolved graphs (c1 and c2).
However, within each graph, the same OliveOil instance is shared in the PerRequest configuration, whereas they are different in the Unique configuration.
Domain Objects and IDataErrorInfo
Occasionally I get a question about whether it is reasonable or advisable to let domain objects implement IDataErrorInfo. In summary, my answer is that it's not so much a question about whether it's a leaky abstraction or not, but rather whether it makes sense at all. To me, it doesn't.
Let us first consider the essence of the concept underlying IDataErrorInfo: It provides information about the validity of an object. More specifically, it provides error information when an object is in an invalid state.
This is really the crux of the matter. Domain Objects should be designed so that they cannot be put into invalid states. They should guarantee their invariants.
Let us return to the good old DanishPhoneNumber example. Instead of accepting or representing a Danish phone number as a string or integer, we model it as a Value Object that encapsulates the appropriate domain logic.
More specifically, the class' constructor guarantees that you can't create an invalid instance:
private readonly int number; public DanishPhoneNumber(int number) { if ((number < 112) || (number > 99999999)) { throw new ArgumentOutOfRangeException("number"); } this.number = number; }
Notice that the Guard Clause guarantees that you can't create an instance with an invalid number, and the readonly keyword guarantees that you can't change the value afterwards. Immutable types make it easier to protect a type's invariants, but it is also possible with mutable types - you just need to place proper Guards in public setters and other mutators, as well as in the constructor.
In any case, whenever a Domain Object guarantees its invariants according to the correct domain logic it makes no sense for it to implement IDataErrorInfo; if it did, the implementation would be trivial, because there would never be an error to report.
Does this mean that IDataErrorInfo is a redundant interface? Not at all, but it is important to realize that it's an Application Boundary concern instead of a Domain concern. At Application Boundaries, data entry errors will happen, and we must be able to cope with them appropriately; we don't want the application to crash by passing unvalidated data to DanishPhoneNumber's constructor.
Does this mean that we should duplicate domain logic at the Application Boundary? That should not be necessary. At first, we can apply a simple refactoring to the DanishPhoneNumber constructor:
public DanishPhoneNumber(int number) { if (!DanishPhoneNumber.IsValid(number)) { throw new ArgumentOutOfRangeException("number"); } this.number = number; } public static bool IsValid(int number) { return (112 <= number) && (number <= 99999999); }
We now have a public IsValid method we can use to implement an IDataErrorInfo at the Application Boundary. Next steps might be to add a TryParse method.
IDataErrorInfo implementations are often related to input forms in user interfaces. Instead of crashing the application or closing the form, we want to provide appropriate error messages to the user. We can use the Domain Object to provide validation logic, but the concern is completely different: we want the form to stay open until valid data has been entered. Not until all data is valid do we allow the creation of a Domain Object from that data.
In short, if you feel tempted to add IDataErrorInfo to a Domain Class, consider whether you aren't about to violate the Single Responsibility Principle. In my opinion, this is the case, and you would be better off reconsidering the design.
Comments
Too often i see domain objects implementing a lot of validation code. I think that most of validation logic must be out of domain objects.
DanishPhoneNumber value can't be less than 112. In reality we are modeling - such a phone number just does not exist. So it makes sense to disallow existence of such an object and throw an error immediately.
But there might be cases when domain contains temporary domain object invalidity from specific viewpoint/s.
Consider good old cargo shipment domain from Blue book. Shipment object is invalid and shouldn't be shipped if there's no cargo to ship and yet such a shipment can exist because it's planned out gradually. In these kind of situations - it might make sense to use IDataErrorInfo interface.
We must keep in mind that we are not modeling the real world, but rather the business logic that addresses the real world. In your example, that would be represented by a proper domain object that models that a shipment is still in the planning stage. Let's call this object PlannedShipment.
According to the domain model, PlannedShipment has its own invariants that it must protect, and the point still remains: PlannedShipment itself cannot be in an invalid state. However, PlannedShipment can't be shipped because it has not yet been promoted to a 'proper' Shipment. Such an API is safer because it makes it impossible to introduce errors of the kind where the code attempts to ship an invalid Shipment.
Thanks
A Value Object benefits very much from being immutable, so I always design them that way, but that doesn't mean that I make Entities immutable as well. I usually don't, although I'm sometimes toying with that idea.
In any case, if you have more than 4 or 5 fields in a class (no matter if you fill them through a constructor or via property setters), you most likely have a new class somewhere in there waiting to be set free. Clean Code makes a pretty good case of this. Once again, too many primitives in an Entity is a smell that the Single Responsibility Principle is violated.
With your phone number example in mind, the validation should imho never be encapsulated in the domain object, but belong to a separate validation. When you put validation inside the constructor you will eventually break the Open/closed principle. Of course we have to validate for null input if they will break the functionality, but I would never integrate range check etc. into the class it self.
However, consumers of those Value Objects need not be. While I didn't show it, DanishPhoneNumber could implement IPhoneNumber and all clients consume the interface. That would make DanishPhoneNumber a leaf of a composition while still keeping the architecture open for extensibility.
The point is to define each type so that their states are always consistent. Note that for input gatherers, invalid data is considered consistent in the scope of input gathering. That's where IDataErrorInfo makes sense :)
Second thing I wanted to emphasize is about Your sentence of making sense - we should focus on technology we are using not only to be able to express ourselves, but to be aware (!) of how we are doing it and be able to adjust that.
Patterns, OOP, .NET, POCO and whatnot are tools only. IDataErrorInfo is a tool too. Therefore - if it feels natural to use it to express our domain model (while it's suboptimal cause of arguments You mentioned), there is nothing wrong with using it per se. An agreement that our domain model objects (in contrast to reality) can be invalid if it simplifies things greatly (think ActiveRecord) is a tool too.
To me, internal consistency and the SRP is so important that I would feel more comfortable having IDataErrorInfo outside of domain objects, but there are no absolutes :)
Introducing AutoFixture Likeness
The last time I presented a sample of an AutoFixture-based unit test, I purposely glossed over the state-based verification that asserted that the resulting state of the basket variable was that the appropriate Pizza was added:
Assert.IsTrue(basket.Pizze.Any(p => p.Name == pizza.Name), "Basket has added pizza.");
The main issue with this assertion is that the implied equality expression is rather weak: we consider a PizzaPresenter instance to be equal to a Pizza instance if their Name properties match.
What if they have other properties (like Size) that don't match? If this is the case, the test would be a false negative. A match would be found in the Pizze collection, but the instances would not truly represent the same pizza.
How do we resolve this conundrum without introducing equality pollution? AutoFixture offers one option in the form of the generic Likeness<TSource, TDestination> class. This class offers convention-based test-specific equality mapping from TSource to TDestination and overriding the Equals method.
One of the ways we can use it is by a convenience extension method. This unit test is a refactoring of the test from the previous post, but now using Likeness:
[TestMethod] public void AddWillAddToBasket_Likeness() { // Fixture setup var fixture = new Fixture(); fixture.Register<IPizzaMap, PizzaMap>(); var basket = fixture.Freeze<Basket>(); var pizza = fixture.CreateAnonymous<PizzaPresenter>(); var expectedPizza = pizza.AsSource().OfLikeness<Pizza>(); var sut = fixture.CreateAnonymous<BasketPresenter>(); // Exercise system sut.Add(pizza); // Verify outcome Assert.IsTrue(basket.Pizze.Any(expectedPizza.Equals)); // Teardown }
Notice how the Likeness instance is created with the AsSource() extension method. The pizza instance (of type PizzaPresenter) is the source of the Likeness, whereas the Pizza domain model type is the destination. The expectedPizza instance is of type Likeness<PizzaPresenter, Pizza>.
The Likeness class overrides Equals with a convention-based comparison: if two properties have the same name and type, they are equal if their values are equal. All public properties on the destination must have equal properties on the source.
This allows me to specify the Equals method as the predicate for the Any method in the assertion:
Assert.IsTrue(basket.Pizze.Any(expectedPizza.Equals));
When the Any method evalues the Pizze collection, it executes the Equals method on Likeness, resulting in a convention-based comparison of all public properties and fields on the two instances.
It's possible to customize the comparison to override the behavior for certain properties, but I will leave that to later posts. This post only scratches the surface of what Likeness can do.
To use Likeness, you must add a reference to the Ploeh.SemanticComparison assembly. You can create a new instance using the public constructor, but to use the AsSource extension method, you will need to add a using directive:
using Ploeh.SemanticComparison.Fluent;
Comments
In your example, you are only comparing one property and I know that you can test many properties as well.
Now it is my understanding that given many properties if any property doesn't match, then you'll get a test failure. My question is how to output a message pinpointing which property is causing the test to fail.
On another note, maybe you could ask Adam Ralph how he's integrated the comment section on his blog, which I believe is using the same platform as you are. http://adamralph.com/2013/01/09/blog-post-excerpts-a-new-solution/
David, if you want to get more detailed feedback on which properties don't match, you can use expected.ShouldEqual(actual);
Upcoming talks spring 2010
In the next couple of weeks I will be giving a couple of talks in Copenhagen.
At Community Day 2010 I will be giving two talks on respectively Dependency Injection and TDD.
In early June I will be giving a repeat of my previous CNUG TDD talk.
Sneak view at Castle's WCF Facility
One of Castle Windsor's facilities addresses wiring up of WCF services. So far, the sparse documentation for the WCF Facility seems to indicate that you have to configure your container in a global.asax. That's not much to my liking. First of all, it reeks of ASP.NET, and secondly, it's not going to work if you expose WCF over protocols other than HTTP.
However, now that we know that a custom ServiceHostFactory is effectively a Singleton, a much better alternative is to derive from the WCF Facility's DefaultServiceHost class:
public class FooServiceHostFactory : DefaultServiceHostFactory { public FooServiceHostFactory() : base(FooServiceHostFactory.CreateKernel()) { } private static IKernel CreateKernel() { var container = new WindsorContainer(); container.AddFacility<WcfFacility>(); container.Register(Component .For<FooService>() .LifeStyle.Transient); container.Register(Component .For<IBar>() .ImplementedBy<Bar>()); return container.Kernel; } }
Although it feels a little odd to create a container and then not really use it, but only its Kernel property, this works like a charm. It correctly wires up this FooService:
public class FooService : IFooService { private readonly IBar bar; public FooService(IBar bar) { if (bar == null) { throw new ArgumentNullException("bar"); } this.bar = bar; } #region IFooService Members public string Foo() { return this.bar.Baz; } #endregion }
However, instead of the static CreateKernel method that creates the IKernel instance, I suggest that the WCF Facility utilizes the Factory Method pattern. As the WCF Facility has not yet been released, perhaps there's still time for that change.
In any case, the WCF Facility saves you from writing a lot of infrastructure code if you would like to wire your WCF services with Castle Windsor.
Comments
<installers>
<install assembly="Ploeh.AssemblyContainingWindsorInstallers"/>
</ installers>
See http://stw.castleproject.org/Windsor.Registering-Installers.ashx
Alternatively you could override protected IWindsorInstaller GetInstallers(); method and configure the container entirely in code.
Thoughts?
For the edge cases where adding an Installer isn't enough, I'd still prefer a Factory Method hook in DefaultServiceHostFactory, but being able to specify an Installer in web.config will likely address 90 percent (or more) of scenarios.
Looks good!
If you use Facility's default SH Factory it will look into your web.config for informations about how to configure itself.
ALternativelty you can provide your own subclass of the SH Factory, override its protected IWindsorInstaller[] GetInstallers(); method and then you'll be able to configure the container without using config file.
Don't get me wrong on the Factory Method thing. I don't expect to need it often (if at all), but I just think it would be a good OCP thing to do... Off the top of my head, I can't remember whether there are things you can do to a container that you can't do from an Installer. Maybe there aren't...
I do intend to leave the door open with factory method for people who can't use xml even if it's so minimal (or feel sick when even thinking about xml), but as you said - there really isn't anything you couldn't do from installer so I imagine it would be for emergency cases only.
ServiceHostFactory lifetime
For a while I've been wondering about the lifetime behavior of custom ServiceHostFactory classes hosted in IIS. Does IIS create an instance per request? Or a single instance to handle all requests?
I decided to find out, so I wrote a little test service. The conclusion seems to be that there is only a single instance that servers as a factory for all requests. This is very fortunate, since it gives us an excellent place to host a DI Container. The container can then manage the lifetime of all components, including Singletons that will live for the duration of the process.
If you are curious how I arrived at this conclusion, here's the code I wrote. I started out with this custom ServiceHostFactory:
public class PocServiceHostFactory : ServiceHostFactory { private static int number = 1; public PocServiceHostFactory() { Interlocked.Increment( ref PocServiceHostFactory.number); } protected override ServiceHost CreateServiceHost( Type serviceType, Uri[] baseAddresses) { return new PocServiceHost( PocServiceHostFactory.number, serviceType, baseAddresses); } }
The idea is that every time a new instance of ServiceHostFactory is created, the static number is incremented.
The PocServiceHostFactory just forwards the number to the PocServiceHost:
public class PocServiceHost : ServiceHost { public PocServiceHost(int number, Type serviceType, Uri[] baseAddresses) : base(serviceType, baseAddresses) { foreach (var cd in this.ImplementedContracts.Values) { cd.Behaviors.Add( new NumberServiceInstanceProvider( number)); } } }
The PocServiceHost just forwards the number to the NumberServiceInstanceProvider:
public class NumberServiceInstanceProvider : IInstanceProvider, IContractBehavior { private readonly int number; public NumberServiceInstanceProvider(int number) { this.number = number; } #region IInstanceProvider Members public object GetInstance( InstanceContext instanceContext, Message message) { return this.GetInstance(instanceContext); } public object GetInstance( InstanceContext instanceContext) { return new NumberService(this.number); } public void ReleaseInstance( InstanceContext instanceContext, object instance) { } #endregion #region IContractBehavior Members public void AddBindingParameters( ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior( ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior( ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { dispatchRuntime.InstanceProvider = this; } public void Validate( ContractDescription contractDescription, ServiceEndpoint endpoint) { } #endregion }
The relevant part of NumberServiceInstanceProvider is the GetInstanceMethod that simply forwards the number to the NumberService:
public class NumberService : INumberService { private readonly int number; public NumberService(int number) { this.number = number; } #region INumberService Members public int GetNumber() { return this.number; } #endregion }
As you can see, NumberService simply returns the injected number.
The experiment is now to host NumberService in IIS using PocServiceHostFactory. If there is only one ServiceHostFactory per application process, we would expect that the same number (2) is returned every time we invoke the GetNumber operation. If, on the other hand, a new instance of ServiceHostFactory is created per request, we would expect the number to increase for every request.
To test this I spun up a few instances of WcfTestClient.exe and invoked the operation. It consistently returns 2 across multiple clients and multiple requests. This supports the hypothesis that there is only one ServiceHostFactory per service process.
Comments
http://containerservicehost.codeplex.com/documentation
Fun with literal extensions and Ambient Context
My book contains a section on the Ambient Context pattern that uses a TimeProvider as an example. It's used like this:
this.closedAt = TimeProvider.Current.UtcNow;
Yesterday I was TDDing a state machine that consumes TimeProvider and needed to freeze and advance time at different places in the test. Always on the lookout for making unit tests more readable, I decided to have a little fun with literal extensions and TimeProvider. I ended up with this test:
// Fixture setup var fixture = new WcfFixture(); DateTime.Now.Freeze(); fixture.Register(1.Minutes()); var sut = fixture.CreateAnonymous<CircuitBreaker>(); sut.PutInOpenState(); 2.Minutes().Pass(); // Exercise system sut.Guard(); // Verify outcome Assert.IsInstanceOfType(sut.State, typeof(HalfOpenCircuitState)); // Teardown
There are several items of note. Imagine that we can freeze time!
DateTime.Now.Freeze();
With the TimeProvider and an extension method, we can:
internal static void Freeze(this DateTime dt) { var timeProviderStub = new Mock<TimeProvider>(); timeProviderStub.SetupGet(tp => tp.UtcNow).Returns(dt); TimeProvider.Current = timeProviderStub.Object; }
This effectively sets up the TimeProvider to always return the same time.
Later in the test I state that 2 minutes pass:
2.Minutes().Pass();
I particularly like the grammatically correct English. This is accomplished with a combination of a literal extension and changing the state of TimeProvider.
First, the literal extension:
internal static TimeSpan Minutes(this int m) { return TimeSpan.FromMinutes(m); }
Given the TimeSpan returned from the Minutes method, I can now invoke the Pass extension method:
internal static void Pass(this TimeSpan ts) { var previousTime = TimeProvider.Current.UtcNow; (previousTime + ts).Freeze(); }
Note that I just add the TimeSpan to the current time and invoke the Freeze extension method with the new value.
Last, but not least, I should point out that the PutInOpenState method isn't some smelly test-specific method on the SUT, but rather yet another extension method.
Changing Windsor lifestyles after the fact
I recently had the need to change the lifestyles of all components in a WindsorContainer (read on to the end if you want to know why). This turned out to be amazingly simple to do.
The problem was this: I had numerous components registered in a WindsorContainer, some of them as Singletons, some as Transients and yet again some as PerWebRequest. Configuration was even defined in numerous IWindsorInstallers, including some distributed XML files. I now needed to spin up a second container with the same configuration as the first one, except that the lifestyles should be all Singletons across the board.
This can be easily accomplished by implementing a custom IContributeComponentModelConstruction type. Here's a simple example:
Consider this IWindsorInstaller:
public class FooInstaller : IWindsorInstaller { #region IWindsorInstaller Members public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Component .For<IFoo>() .ImplementedBy<Foo>() .LifeStyle.Transient); } #endregion }
The important point to notice is that it registers the lifestyle as Transient. In other words, this container will always return new Foo instances:
var container = new WindsorContainer(); container.Install(new FooInstaller());
We can override this behavior by adding this custom IContributeComponentModelConstruction:
public class SingletonEqualizer : IContributeComponentModelConstruction { public void ProcessModel(IKernel kernel, ComponentModel model) { model.LifestyleType = LifestyleType.Singleton; } }
In this very simple example, I always set the lifestyle type to the same value, but obviously we can write as complex code in the ProcessModel method as we would like. We can now configure the container like this:
var container = new WindsorContainer(); container.Kernel.ComponentModelBuilder .AddContributor(new SingletonEqualizer()); container.Install(new FooInstaller());
With this configuration we will now get the same instance of Foo every time we Resolve IFoo.
We did I need this? Because my application is a web application and I'm using the PerWebRequest lifestyle in a number of places. However, I needed to spin up a second container that would compose object hierarchies for a background process. This background process needs the same component configuration as the rest of the application, but can't use the PerWebRequest lifestyle as there will be no web request available to the background process. Hence the need to change lifestyles across the board.
Why I'm migrating from MSTest to xUnit.net
About a month ago I decided to migrate from MSTest to xUnit.net, and while I am still in the process, I haven't regretted it yet, and I don't expect to. AutoFixture has already moved over, and I'm slowly migrating all the sample code for my book.
Recently I was asked why, which prompted me to write this post.
I'm not moving away from MSTest for one single reason. It's rather like lots of small reasons.
When I originally started out with TDD, I used nUnit - it was more or less the only unit testing framework available for .NET at the time. When MSTest came, the change was natural, since I worked for Microsoft at the time. This is not the case anymore, but it still took me most of a year to finally abandon MSTest.
There was one thing that really made me cling to MSTest, and that was the IDE integration, but over time, I started to realize that this was the only reason, and even that was getting flaky.
When I started to think about all the things that left me dissatisfied, making the decision was easy:
- First of all, MSTest isn't extensible, but xUnit.net is. In xUnit.net, I can extend the Fact or Theory attributes (and I intent to), while in MSTest, I will have to play with the cards I've been dealt. I think I could live with all the other issues if I could just have this one, but no.
- MSTest has no support for parameterized test. xUnit.net does (via the Theory attribute).
- MSTest has no Assert.Throws, although I requested this feature a long time ago. Now Visual Studio 2010 is out, but Assert.Throws is still nowhere in sight.
- MSTest has no x64 support. Tests always run as x86. Usually it's no big deal, but sometimes it's a really big deal.
- In MSTest, to write unit tests, you must create a special Unit Test Project, and those are only available for C# and VB.net. Good luck trying to write unit tests in a more exotic .NET language (like F# on Visual Studio 2008). xUnit.net doesn't have this problem.
- MSTest uses Test Lists and .vsmdi files to maintain test lists. Why? I don't care, I just want to execute my tests, and the .vsmdi files are in the way. This is particularly bad when you use TFS, but I'm also moving away from TFS, so that wouldn't have continued to be that much of an issue. Still: try having more than one .sln file with unit tests in the same folder, and watch funny things happen because they need to share the same .vsmdi file.
- I suppose it's because of the .vsmdi files, but sometimes I get a Test run error if I delete a test and run the tests immediately after. That's a false positive, if anyone cares.
- MSTest gives special treatment to its own AssertionException, which gets nice formatting in the Test Results window. All other exceptions (like verification exceptions thrown by Moq or Rhino Mocks are rendered near-intelligible because MSTest thinks it's very important to report the fully qualified name of the exception before its message. Most of the time, you have to open the Test Details window to see the exception message.
- Last, but not least, I often get cryptic exception messages like this one: Column 'id_column, runid_column' is constrained to be unique. Value '8c84fa94-04c1-424b-9868-57a2d4851a1d, d7471c5e-522f-43d3-b2c5-8f5cab55af0e' is already present. This appears in a very annoying modal MessageBox, but clicking OK and retrying usually works, although sometimes it even takes two or three attempts before I can get past this error.
It not one big thing, it's just a lot of small, but very annoying things. After three iterations (VS2005, VS2008 and now VS2010) these issue have still to be addressed, and I got tired of waiting.
So far, I can only say that I have none of these problems with xUnit.net and the IDE integration provided by TestDriven.NET. It's just a much smoother experience with much less friction.
Comments
Interesting post about moving away from "out-of-the-box" Microsoft tools. I've made this move about a year ago, and I can't regret about it.
Another point that you mentioned in your post and that really caught my attention was the fact that you are also moving away from TFS. Since I'm starting my own startup here, the budget is really short and we are looking for cheaper alternatives to TFS.
Here, we really like Mercurial HG and we are basing out SCM on it. However, I'm having difficulty finding tools for bug and feature tracking. Can you share with me in which direction you are moving away from TFS?
In Safewhere, we are currenlty trying out AgileZen for work item tracking. For AutoFixture, I just use the tools provided with CodePlex.
One reason is that xUnit.net has a pretty good extensibility story, and as I do have some plans in that direction, that's a pretty big issue for me. Last time I checked, the extensibility story for NUnit didn't match xUnit.net.
NUnit has a design bug when it comes to Fixture management, because it creates only a single instance of a test class and invokes all the test methods on that instance. This may have been fixed since the last time I looked, but in any case, I better like xUnit.net's philosphy of using the test class' constructor for Fixture Setup (if any) and implementing IDisposable for Fixture Teardown.
As I said, both items are based on somewhat dated knowledge on my part, so none of them may apply anymore.
AutoFixture 1.1
AutoFixture 1.1 is now available on the CodePlex site! Compared to the Release Candidate, there are no changes.
The 1.1 release page has more details about this particular release, but essentially this is the RC promoted to release status.
Release 1.1 is an interim release that addresses a few issues that appeared since the release of version 1.0. Work continues on AutoFixture 2.0 in parallel.
Comments