Over a million developers have joined DZone.

Unit Testing Legacy Code With C# 3.0 Language Features


We all have some old legacy code from the C# 2.0 days floating around--Legacy in the Feathers sense of the word that there are no unit tests around it.  We also know that we eventually need to get some tests around that old code just to nail it down.  Did you know that you can test C# 2.0 source code from C# 3.0 assemblies?  It seems incredibly obvious in hindsight but it had never even occurred to me until Patrice Beavuis was kind enough to point it out during an email conversation on unit testing a few months ago.  Why would you want to do this?  Because with C# 3.0 you can take advantage of more modern testing and mocking frameworks like Moq.

Take this bit of "legacy code", for example...

    public class AccountManager
private readonly IInterestService _interestService;

public AccountManager(IInterestService interestService)
_interestService = interestService;

public void TransferFunds(double amount, Account sourceAccount, Account destinationAccount)

public void AddInterest(Account account)
account.Deposit(account.Balance * _interestService.CurrentInterestRate);

The AccountManager class is a standard C# 2.0 class designed to do everything a bank could do.  That is, it can transfer money between accounts and it can add interest to accounts.  This is a nice little class and does everything it should...we think.  We can only assume it does everything we need it to because there are no unit tests.  However, we wrote this class 2 years ago and have since transitioned to Visual Studio 2008 and the wonderful world of C# 3.0.

Let's imagine that we need a test to verify that we can transfer money between two accounts.  Sure we can write a unit test to verify this with C# 2.0 technologies, but just because the class under test is 2.0 doesn't mean our tests have to be.  Let's use Moq and fully exploit our 3.0 technologies...

public void Accounts_can_accrue_interest()
var account = new Account(50.0);

var interestServiceMock = new Mock<IInterestService>();
interestServiceMock.Expect(service => service.CurrentInterestRate).Returns(0.10);

var manager = new AccountManager(interestServiceMock.Object);

Assert.Equal(55.0, account.Balance);

Notice the use of the lambda expression to set the expectation on the mocked instance of IInterestService.  Because we're using a C# 3.0 class library to test our code we can take full advantage of these features, even though our class under test was created with C# 2.0! 

You can download the sample from here.

Remember, just because your legacy code is using an old technology doesn't mean your tests have to!



Published at DZone with permission of Jeremy Jarrell. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}