TDD and Commerce Server 2007: Custom Rollback
Wednesday, January 28th, 2009comments
In my previous post I mentioned using a TransactionScope to rollback Commerce Server database updates, when unit testing, may not always work. Turns out it doesn’t work with the profile subsystem.
To verify this, I coded an example similar to the address example on MSDN, resulting in the following test:
[Fact]
public void Should_save_address_changes() {
var addressId = Guid.NewGuid();
var addressService = new AddressService(TestProfileContext);
var address = createNewAddress(addressService, addressId);
addressService.Save(address);
var savedAddress = addressService.Find(addressId);
Assert.Equal(address.Line1, savedAddress.Line1);
Assert.Equal(address.City, savedAddress.City);
Assert.Equal(address.State, savedAddress.State);
Assert.Equal(address.ZipCode, savedAddress.ZipCode);
}
For this test, I extended the CommerceFixture class (created in my previous post) to create a TestProfileContext instance. If this test is executed, it will always save a new address to the Commerce Server Profiles Database. If we try adding an AutoRollback attribute to the test, the new address doesn’t get rolled back.
To fix this we can call TestProfileContext.DeleteProfile when the test completes. An easy way to do this, while making the code exception safe, is to create a scope class that implements IDisposable. This allows us to wrap the test in a using block, reducing the amount of code we need to type. Here’s an example implementation:
public class ProfileScope : IDisposable {
private readonly ProfileContext _profileContext;
private readonly string _keyValue;
private readonly string _profileType;
public ProfileScope(ProfileContext context, string keyValue, string profileType) {
_profileContext = context;
_keyValue = keyValue;
_profileType = profileType;
}
public void Dispose() {
_profileContext.DeleteProfile(_keyValue, _profileType);
}
}
Now we can update the test, adding a using block with our scope object:
[Fact]
public void Should_save_address_changes() {
//arrange
using (new ProfileScope(TestProfileContext, addressId.ToString(),
AddressService.ProfileName)) {
addressService.Save(address);
//assert
}
}
We can trim the code down even further by adding a helper method to the base test class, CommerceFixture:
public class CommerceFixture {
...
public static ProfileScope ProfileScope(string keyValue, string profileType){
return new ProfileScope(TestProfileContext, keyValue, profileType);
}
...
}
Which gives us our final version:
[Fact]
public void Should_save_address_changes() {
//arrange
using (ProfileScope(addressId.ToString(), AddressService.ProfileName)) {
addressService.Save(address);
//assert
}
}
You can download the code for this example here.

Add New Comment
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Add New Comment