Created
September 27, 2016 19:48
-
-
Save CopperStarSystems/98f8038744e433acaf8cc8d947b8b53d to your computer and use it in GitHub Desktop.
C# class after refactoring to improve testability
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is an example class illustrating some common patterns | |
// to simplify unit testing | |
public class MuchEasierToTest{ | |
// Changed to ISomeModel so we can inject a mock model during testing | |
ISomeModel model; | |
IPath path; | |
// Update constructor to take ISomeOtherDependency so we can inject a mock instance | |
// during testing. Same thing for ISomeModelFactory and IPath. | |
public ReallyHardToTest(ISomeOtherDependency otherDependency, ISomeModelFactory someModelFactory, IPath path){ | |
// Invoke the method on our factory instead of directly creating a Model instance | |
// Our tests can now verify that a new ISomeModel instance is created in the constructor | |
model = someModelFactory.Create(); | |
// Because we are programming against ISomeOtherDependency, we can verify that this | |
// method is invoked at test time. | |
otherDependency.DoSomething(); | |
this.path = path; | |
} | |
public void SetFilename(string fileName){ | |
// Invoke method on injected IPath instance instead of the | |
// static Path class. | |
model.Filename = path.GetFileName(fileName); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code implements a wrapper around the static Path class. | |
// The interface allows us to inject a mock IPath instance at | |
// test time (for example when testing the MuchEasierToTest class). | |
public interface IPath{ | |
string GetFileName(string fileName); | |
} | |
public class PathImpl : IPath { | |
public string GetFileName(string fileName){ | |
return Path.GetFileName(fileName); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Introducing an interface enables us to mock SomeModel in tests | |
public interface ISomeModel{ | |
string FileName{get;set;} | |
} | |
// Same concrete SomeModel type as in original file. | |
public class SomeModel : ISomeModel{ | |
public string FileName{get;set;} | |
} | |
// Introducing a factory interface enables us to verify | |
// that creation logic is invoked and also to control | |
// the result of creation by returning a mock instance | |
public interface ISomeModelFactory{ | |
ISomeModel Create(); | |
} | |
// Notice that the factory class only has one responsibility: | |
// To give us a new instance of a type implementing ISomeModel. | |
// At test time, we will be able to inject a mock factory instance | |
// and control what it returns, giving us better control over | |
// our test coverage. | |
public class SomeModelFactory : ISomeModelFactory{ | |
public ISomeModel Create(){ | |
return new SomeModel(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Introducing an interface enables us to mock SomeOtherDependency in tests | |
public interface ISomeOtherDependency{ | |
void DoSomething(); | |
} | |
// Same concrete SomeOtherDependency type as original file | |
public class SomeOtherDependency : ISomeOtherDependency{ | |
public void DoSomething(){ | |
// Just here for illustration. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment