Hullo folks! :)
In yesterday's article, "C#: Unit Testing with SharpDevelop and NUnit", we learned about unit tests: what they are, why we use them, and how we write and execute them. The article ended with a number of insights about them. One of these insights was that it is not easy to write unit tests for code that relies on databases, the network, or other external resources.
In today's article, we're going to address this problem by learning about mocking and dependency injection. These might sound like big buzz-words, but you'll see in this article that they're really nothing special. To see this in action, we'll write a small program that loads a file from the hard disk and sorts it alphabetically, line by line.
This article is a bit on the advanced side, so ideally you should know your OOP and also be familiar with basic unit testing (e.g. from yesterday's article) before reading it.
Start off by creating a new Console Application in SharpDevelop. When this is done, add a new class (right click on project in Projects window, Add -> New Item...) and name it Sorter. At the top, add the following to allow us to read files and use lists:
using System.Collections.Generic;
using System.IO;
Next, add a member variable in which we can store the lines in the file:
private String[] lines;
Add a constructor in Sorter that takes the name of the file to sort, and loads it into the variable we just declared:
public Sorter(String filename)
{
this.lines = File.ReadAllLines(filename);
}
Now, add a method that actually does the sorting:
public String[] GetSortedLines()
{
List<String> sortedLines = new List<String>(lines);
sortedLines.Sort();
return sortedLines.ToArray();
}
This way of sorting is not the only one and not necessarily the best, but I chose it because it's simple and doesn't change the lines variable, just in case you want to keep it in its original unsorted format for whatever reason.
Let's try and write a test for this code. Add a new class called SorterTest (as I've already mentioned in yesterday's article, people usually put tests into their own project, but I'm trying to teach one concept at a time here). After adding a reference to nunit.framework.dll (check yesterday's article in case you're lost), set up the SorterTest.cs file as follows:
[Test]
public void GetSortedLinesTest()
{
Sorter sorter = new Sorter("test.txt");
String[] s = sorter.GetSortedLines();
Assert.AreEqual("Gates, Bill", s[0]);
Assert.AreEqual("Norris, Chuck", s[1]);
Assert.AreEqual("Torvalds, Linus", s[2]);
Assert.AreEqual("Zuckerberg, Mark", s[3]);
}
Create a file in your bin\Debug folder called test.txt and put the following in it:
Zuckerberg, Mark
Norris, Chuck
Gates, Bill
Torvalds, Linus
Open the Unit Tests window in SharpDevelop (View -> Tools -> Unit Tests) and run it. You can see that the test passes.
Great.
Actually, this is the wrong way of writing unit tests for this kind of thing. We have a dependency on the filesystem. What would happen if that file suddenly disappears? As a matter of fact, we are supposed to be testing the sorting logic, not whether the file is available or not.
In order to do this properly, we're going to have to refactor our code. We need to take our file loading code out of there. Create a new class called FileLoader and add the following at the top:
using System.IO;
...and then set up FileLoader as follows:
public class FileLoader
{
private String[] lines;
public String[] Lines
{
get
{
return this.lines;
}
}
public FileLoader(String filename)
{
this.lines = File.ReadAllLines(filename);
}
}
In Sorter, remove the constructor as well as the using System.IO; and the lines variable. Instead, we'll pass our FileLoader as a parameter:
public String[] GetSortedLines(FileLoader loader)
{
List<String> sortedLines = new List<String>(loader.Lines);
sortedLines.Sort();
return sortedLines.ToArray();
}
This is called dependency injection: instead of creating the dependency (in our case a file) from within the Sorter class, we pass it as a parameter. This allows us to substitute the dependency for a fake (known as a mock). To do this, we'll need to take advantage of polymorphism (see "C# OOP: Abstract classes, fruit, and polymorphism". Create an interface (when adding a new item, instead of Class, specify Interface) and name it IFileLoader:
An interface is a form of abstract class - it cannot be instantiated, and it declares methods and/or properties that don't have any implementation because they should be implemented by the classes that inherit from (or implement) that interface. In an interface, however, no methods/properties have an implementation. It is used as a contract, saying that any class implementing the interface must implement its methods/properties. In our case, IFileLoader will be this:
public interface IFileLoader
{
String[] Lines
{
get;
}
}
We then specify that FileLoader implements IFileLoader; this is the same as saying that FileLoader inherits from IFileLoader:
public class FileLoader : IFileLoader
FileLoader already has the necessary Lines property, so we're fine. Next, we replace the FileLoader parameter in Sorter.GetSortedLines() with an instance of the interface:
public String[] GetSortedLines(IFileLoader loader)
This allows us to pass, as a parameter, any class that implements IFileLoader. So we can create a class, MockFileLoader, that provides a hardcoded list of names:
public class MockFileLoader : IFileLoader
{
private String[] lines = { "Zuckerberg, Mark", "Norris, Chuck", "Gates, Bill", "Torvalds, Linus" };
public String[] Lines
{
get
{
return this.lines;
}
}
}
We can now rewrite our unit test like this:
[Test]
public void GetSortedLinesTest()
{
IFileLoader loader = new MockFileLoader();
Sorter sorter = new Sorter();
String[] s = sorter.GetSortedLines(loader);
Assert.AreEqual("Gates, Bill", s[0]);
Assert.AreEqual("Norris, Chuck", s[1]);
Assert.AreEqual("Torvalds, Linus", s[2]);
Assert.AreEqual("Zuckerberg, Mark", s[3]);
}
If you run the unit test, you'll find that it works just like before, just that this time our unit test isn't dependent on any file and can run just file without one:
In this article, we have seen how to create mock classes that emulate the functionality of our normal classes, but can replace them in unit tests when dependencies exist. To facilitate this, both the mock class and the normal class implement a common interface, and an instance of this interface is passed as a parameter to the method being tested. This is called dependency injection and allows us to control what is being passed to the method.
It is not always easy to write mocks. First, as this article has shown, code may need to be refactored in order to isolate dependencies and support dependency injection. Secondly, mocking complex classes (e.g. an IMAP server) can take a great deal of effort and might not necessarily be worth it. Use your own judgement to decide whether you need unit tests in such situations.
Thanks for reading, and be sure to visit here often to read more articles that might be useful.
Showing posts with label bill gates. Show all posts
Showing posts with label bill gates. Show all posts
Sunday, September 22, 2013
C#: Mocking and Dependency Injection for Unit Testing a File Sorting Program
Labels:
advanced,
bill gates,
chuck norris,
dependency injection,
files,
inheritance,
interfaces,
io,
linus torvalds,
lists,
mark zuckerberg,
mocking,
nunit,
oop,
polymorphism,
properties,
sharpdevelop,
sorting,
unit testing
Friday, August 9, 2013
C# OOP: Encapsulation and Properties
Hi everyone!
Some recent articles have discussed different aspects of Object Oriented Programming. Today we'll talk about controlling access to members (variables or methods) of our classes.
Let's begin with a scenario. We have an accounting program that keeps track of a person's money. First, we need to use the following library:
using System.Collections.Generic;
Then we declare a Transaction class to contain the details of each transaction (deposits, withdrawals... basically anything that affects the amount of money in the account):
class Transaction
{
public DateTime date;
public String detail;
public float amount;
public Transaction(DateTime date, String detail, float amount)
{
this.date = date;
this.detail = detail;
this.amount = amount;
}
}
We also need an Account class to keep the overall account information, as well as a list of all the transactions in the account:
class Account
{
public String name;
public float balance;
public List<Transaction> transactions;
public Account(String name)
{
this.name = name;
this.balance = 0.0f;
this.transactions = new List<Transaction>();
}
public void Show()
{
Console.WriteLine("Account for {0}", name);
Console.WriteLine();
foreach (Transaction transaction in transactions)
{
Console.WriteLine("{0:yyyy-MM-dd} {1, -30} {2}",
transaction.date, transaction.detail, transaction.amount.ToString("0.00").PadLeft(8, ' '));
}
Console.WriteLine();
Console.WriteLine("Balance: {0:0.00}", this.balance);
}
}
We can now see how this works with some sample code in Main():
Console.Title = "C# Encapsulation with Accounting";
Transaction trans1 = new Transaction(new DateTime(2013, 08, 07), "Deposit: My first salary", 20.0f);
Transaction trans2 = new Transaction(new DateTime(2013, 08, 08), "Withdrawal... need cash", -15.0f);
Transaction trans3 = new Transaction(new DateTime(2013, 08, 09), "Deposit: Birthday present", 10.0f);
Account account = new Account("Bill Gates");
account.transactions.Add(trans1);
account.balance += trans1.amount;
account.transactions.Add(trans2);
account.balance += trans2.amount;
account.transactions.Add(trans3);
account.balance += trans3.amount;
account.Show();
Console.ReadKey(true);
So here we've created an account for Bill Gates and added three transactions. The Show() method gives us a picture of the account status and history:
That's great. But what if the guy writing the code in Main() forgets to update the account balance? The sum of the transactions won't agree with the value in the balance member variable. We could provide a method to take care of this in Account:
public void AddTransaction(Transaction transaction)
{
transactions.Add(transaction);
this.balance += transaction.amount;
}
...and while this is certainly useful, it doesn't really solve the problem. Because while a programmer might use this method, there is nothing to keep him from updating transactions and balance separately, the old way, as illustrated earlier. Even worse, someone might actually tamper with them, potentially removing transactions or modifying the balance into something different.
The one thing we've been doing wrong all along is declaring all member variables and methods in our classes as public. When they're public, it means anyone can touch them. We can restrict access to members by using a protected or private access modifier instead of public (there are others, but they're not important at this stage).
Once we switch the member variables in the Account class to private:
private String name;
private float balance;
private List<Transaction> transactions;
...then the program won't compile:
That's because we're accessing these private member variables directly from within Main(). When a variable is private, it means that only code within the same class can access it. So it's ok for the AddTransaction() method we added earlier to use the transactions member variable, but the code in Main() can't. Instead, the code in Main() must be refactored to use AddTransaction():
account.AddTransaction(trans1);
account.AddTransaction(trans2);
account.AddTransaction(trans3);
With this change, it compiles just as well. So we've just seen how we can prevent users of a class from tampering with its internal state, and yet still do useful stuff with it via the methods it does expose as public. This is called encapsulation, and it effectively means "data hiding". In OOP it is usually the case that our classes provide a public interface by which other objects can use them, but they hide all the rest from public view.
Naturally, it is often the case that other objects want to access member variables for legitimate reasons. In that case, instead of making the member variable public, we add methods allowing access to them:
public String GetName()
{
return this.name;
}
public void SetName(String value)
{
this.name = value;
}
public float GetBalance()
{
return this.balance;
}
These are called getter and setter methods, because they allow you to retrieve and modify the variable. A setter can be omitted (as with the balance variable) if that variable is meant to be read-only.
Although using getter and setter methods is a great way of using encapsulation in any OOP language, C# provides the use of properties, which do the same thing but are arguably more elegant:
public String Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
public float Balance
{
get
{
return this.balance;
}
}
Properties are actually converted to getter and setter methods during compilation, but this process is transparent to you (the programmer). Using them in code is pretty easy:
Console.WriteLine("{0} has {1} Euros in his account.", account.Name, account.Balance);
Right, so what about the protected access modifier? It's like private, but also allows subclasses to access a class's members. You should use it sparingly, or not at all. Scott Meyers explains why in his excellent book "Effective C++: 55 Specific Ways to Improve Your Programs and Designs". When you make something public, there are potentially infinitely many places from where it can be accessed and modified. So if you decide to change that variable (e.g. remove it and replace it with a computation), you have to refactor all those places. If something is protected, it can be accessed from any subclass, so there are still porentially infinitely many places from where it can be modified. If you want a subclass to access a variable, your best bet is to encapsulate it using a getter/setter pair or a property, and have the subclass access that.
To see this idea in action, let's remove the Account class's balance variable and replace it with a sum of the transaction amounts:
public float Balance
{
get
{
float bal = 0.0f;
foreach (Transaction transaction in this.transactions)
{
bal += transaction.amount;
}
return bal;
}
}
So like this, any other classes accessing the Balance property may continue to do so without needing to refactor anything. In our case we only need to make some small changes in the Account class itself (no need to maintain a separate balance variable any more in the constructor and in AddTransaction(), and use the property instead of the variable in Show()). But if we had to refactor a hundred other classes to remove the balance variable, it would have been a very expensive change.
Cool. So in this article we learned why we should hide certain internal class data from outside code that might tamper with it - a practice called encapsulation. Encapsulation is so important that, together with inheritance and polymorphism, it is known as one of the Three Pillars of OOP. We also learned about access modifiers (public, protected, private), getter/setter methods, as well as properties - something unique to C#.
From these OOP articles you might begin to see what OOP is really about: the complex relationships between objects make designing OOP software quite a challenge. It's also quite fun. :)
I hope you enjoyed this article, and check back for more! :)
Some recent articles have discussed different aspects of Object Oriented Programming. Today we'll talk about controlling access to members (variables or methods) of our classes.
Let's begin with a scenario. We have an accounting program that keeps track of a person's money. First, we need to use the following library:
using System.Collections.Generic;
Then we declare a Transaction class to contain the details of each transaction (deposits, withdrawals... basically anything that affects the amount of money in the account):
class Transaction
{
public DateTime date;
public String detail;
public float amount;
public Transaction(DateTime date, String detail, float amount)
{
this.date = date;
this.detail = detail;
this.amount = amount;
}
}
We also need an Account class to keep the overall account information, as well as a list of all the transactions in the account:
class Account
{
public String name;
public float balance;
public List<Transaction> transactions;
public Account(String name)
{
this.name = name;
this.balance = 0.0f;
this.transactions = new List<Transaction>();
}
public void Show()
{
Console.WriteLine("Account for {0}", name);
Console.WriteLine();
foreach (Transaction transaction in transactions)
{
Console.WriteLine("{0:yyyy-MM-dd} {1, -30} {2}",
transaction.date, transaction.detail, transaction.amount.ToString("0.00").PadLeft(8, ' '));
}
Console.WriteLine();
Console.WriteLine("Balance: {0:0.00}", this.balance);
}
}
We can now see how this works with some sample code in Main():
Console.Title = "C# Encapsulation with Accounting";
Transaction trans1 = new Transaction(new DateTime(2013, 08, 07), "Deposit: My first salary", 20.0f);
Transaction trans2 = new Transaction(new DateTime(2013, 08, 08), "Withdrawal... need cash", -15.0f);
Transaction trans3 = new Transaction(new DateTime(2013, 08, 09), "Deposit: Birthday present", 10.0f);
Account account = new Account("Bill Gates");
account.transactions.Add(trans1);
account.balance += trans1.amount;
account.transactions.Add(trans2);
account.balance += trans2.amount;
account.transactions.Add(trans3);
account.balance += trans3.amount;
account.Show();
Console.ReadKey(true);
So here we've created an account for Bill Gates and added three transactions. The Show() method gives us a picture of the account status and history:
That's great. But what if the guy writing the code in Main() forgets to update the account balance? The sum of the transactions won't agree with the value in the balance member variable. We could provide a method to take care of this in Account:
public void AddTransaction(Transaction transaction)
{
transactions.Add(transaction);
this.balance += transaction.amount;
}
...and while this is certainly useful, it doesn't really solve the problem. Because while a programmer might use this method, there is nothing to keep him from updating transactions and balance separately, the old way, as illustrated earlier. Even worse, someone might actually tamper with them, potentially removing transactions or modifying the balance into something different.
The one thing we've been doing wrong all along is declaring all member variables and methods in our classes as public. When they're public, it means anyone can touch them. We can restrict access to members by using a protected or private access modifier instead of public (there are others, but they're not important at this stage).
Once we switch the member variables in the Account class to private:
private String name;
private float balance;
private List<Transaction> transactions;
...then the program won't compile:
That's because we're accessing these private member variables directly from within Main(). When a variable is private, it means that only code within the same class can access it. So it's ok for the AddTransaction() method we added earlier to use the transactions member variable, but the code in Main() can't. Instead, the code in Main() must be refactored to use AddTransaction():
account.AddTransaction(trans1);
account.AddTransaction(trans2);
account.AddTransaction(trans3);
With this change, it compiles just as well. So we've just seen how we can prevent users of a class from tampering with its internal state, and yet still do useful stuff with it via the methods it does expose as public. This is called encapsulation, and it effectively means "data hiding". In OOP it is usually the case that our classes provide a public interface by which other objects can use them, but they hide all the rest from public view.
Naturally, it is often the case that other objects want to access member variables for legitimate reasons. In that case, instead of making the member variable public, we add methods allowing access to them:
public String GetName()
{
return this.name;
}
public void SetName(String value)
{
this.name = value;
}
public float GetBalance()
{
return this.balance;
}
These are called getter and setter methods, because they allow you to retrieve and modify the variable. A setter can be omitted (as with the balance variable) if that variable is meant to be read-only.
Although using getter and setter methods is a great way of using encapsulation in any OOP language, C# provides the use of properties, which do the same thing but are arguably more elegant:
public String Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
public float Balance
{
get
{
return this.balance;
}
}
Properties are actually converted to getter and setter methods during compilation, but this process is transparent to you (the programmer). Using them in code is pretty easy:
Console.WriteLine("{0} has {1} Euros in his account.", account.Name, account.Balance);
Right, so what about the protected access modifier? It's like private, but also allows subclasses to access a class's members. You should use it sparingly, or not at all. Scott Meyers explains why in his excellent book "Effective C++: 55 Specific Ways to Improve Your Programs and Designs". When you make something public, there are potentially infinitely many places from where it can be accessed and modified. So if you decide to change that variable (e.g. remove it and replace it with a computation), you have to refactor all those places. If something is protected, it can be accessed from any subclass, so there are still porentially infinitely many places from where it can be modified. If you want a subclass to access a variable, your best bet is to encapsulate it using a getter/setter pair or a property, and have the subclass access that.
To see this idea in action, let's remove the Account class's balance variable and replace it with a sum of the transaction amounts:
public float Balance
{
get
{
float bal = 0.0f;
foreach (Transaction transaction in this.transactions)
{
bal += transaction.amount;
}
return bal;
}
}
So like this, any other classes accessing the Balance property may continue to do so without needing to refactor anything. In our case we only need to make some small changes in the Account class itself (no need to maintain a separate balance variable any more in the constructor and in AddTransaction(), and use the property instead of the variable in Show()). But if we had to refactor a hundred other classes to remove the balance variable, it would have been a very expensive change.
Cool. So in this article we learned why we should hide certain internal class data from outside code that might tamper with it - a practice called encapsulation. Encapsulation is so important that, together with inheritance and polymorphism, it is known as one of the Three Pillars of OOP. We also learned about access modifiers (public, protected, private), getter/setter methods, as well as properties - something unique to C#.
From these OOP articles you might begin to see what OOP is really about: the complex relationships between objects make designing OOP software quite a challenge. It's also quite fun. :)
I hope you enjoyed this article, and check back for more! :)
Labels:
access modifiers,
accounting,
bill gates,
c#,
effective c++,
encapsulation,
formatstrings,
getters,
intermediate,
lists,
oop,
private,
properties,
protected,
public,
scott meyers,
setters,
sharpdevelop
Subscribe to:
Posts (Atom)