the following is the original text of the book 《The Art of Unit Testing, Second Edition》: Extract an interface to allow replacing underlying implementation
- In this technique, you need to break out the code that touches the filesystem into a separate class. That way you can easily distinguish it and later replace the call to that class from your tests (as was shown in figure 3.3). This first listing shows the places where you need to change the code.
Listing 3.1 Extracting a class that touches the filesystem and calling it
public bool IsValidLogFileName(string fileName)
{
FileExtensionManager mgr =
new FileExtensionManager();
return mgr.IsValid(fileName);
}
class FileExtensionManager
{
public bool IsValid(string fileName)
{
//read some file here
}
}
- Next, you can tell your class under test that instead of using the concrete FileExtensionManager class, it will deal with some form of ExtensionManager, without knowing its concrete implementation. In.NET, this could be accomplished by either using a base class or an interface that FileExtensionManager would extend.The next listing shows the use of a new interface in your design to make it more testable. Figure 3.4 showed a diagram of this implementation.
Listing 3.2 Extracting an interface from a known class
public class FileExtensionManager : IExtensionManager
{
public bool IsValid(string fileName)
{
...
}
}
public interface IExtensionManager
{
bool IsValid (string fileName);
}
//the unit of work under test:
public bool IsValidLogFileName(string fileName)
{
IExtensionManager mgr =
new FileExtensionManager();
return mgr.IsValid(fileName);
}
- You create an interface with one IsValid (string) method and make FileExtensionManager implement that interface. It still works exactly the same way, only now you can replace the “real” manager with your own “fake” manager, which you’ll create later to support your test.You still haven’t created the stub extension manager, so let’s create that right now.It’s shown in the following listing
Question: I don’t understand why adding an interface makes it easier to distinguish and replace class calls later? Is this question in the scope of design patterns? Should I learn some design patterns to better understand this question?
Aucun commentaire:
Enregistrer un commentaire