October 23, 2021
Nikolay Kostov (Nikolay.IT)
Topics covered:
Testable Code
Fakes, Mocks, Stubs
Mocking
Moq
JustMock
Video (in Bulgarian)
VIDEO
Presentation Content
How to Write Testable Code
Inversion of Control Pattern
There is a decoupling of the execution of a certain task from implementation
Every module can focus on what it is designed for
Modules make no assumptions about what other systems do but rely on their contracts
Replacing modules has no side effect on other modules
More info at http://en.wikipedia.org/wiki/Inversion_of_control
How to Write Testable Code
Public API should work with interfaces, not implementation classes (IEnumerable vs. List)
Bad code:
public Card[] Cards { get ; private set ; }
public IList<ICard> Cards { get ; private set ; }
Dependency Injection
IoC Containers
Consists of:
A dependent consumer
A declaration of a component’s dependencies, defined as interface contracts
An injector (sometimes referred to as a provider or container) that creates instances of classes that implement a given dependency interface on request
How to Write Testable Code
public interface IViewBase {}
public interface IPresenterBase {}
public class MemoryLayoutView : IViewBase {}
public class MemoryLayoutPresenter : IPresenterBase
{
private MemoryLayoutView view = new MemoryLayoutView();
public MemoryLayoutPresenter () { }
}
How to Write Testable Code
public interface IViewBase {}
public interface IPresenterBase {}
public class MemoryLayoutView : IViewBase {}
public class MemoryLayoutPresenter : IPresenterBase
{
private IViewBase view;
public MemoryLayoutPresenter (IViewBase myView )
{
this .view = myView;
}
}
public class Program {
static void Main () {
InjectionContainer.Create<typeof (MemoryLayoutPresenter)>();
}
}
Faking
Makes Unit Testing more effective
Avoid writing boring boilerplate code
Isolate dependencies among units
Asserts expectations for code quality
Ex: Checks that a method is called only once
Fake vs Mock vs Stub
Fake - objects actually have working implementations but with limited capabilities.
Stub - provide canned answers to calls made during the test. May record information about calls.
Mock - objects pre-programemd with expectations against we can assert
Mocking
You can use inheritance to replace logic
Maintainability - hard to achieve it
Gets really complicated
Could lead to errors
Could create fake objects
Set the desired behaviour of the objects
Verify (Assert) against the fake objects
Constrained frameworks usually work by generating code at runtime that inherits and overrides interfaces or base classes
In .NET, constrained frameworks are unable to fake:
static methods
nonvirtual methods
nonpublic methods
and more
Unconstrained frameworks could be used as constrained as well
Using unconstrained isolation frameworks has some advantage
You can write unit tests for previously untestable code
You can fake third-party systems that you can’t control
If you don’t pay close attention, some tests can become unmaintainable
Moq
Moq syntax
The most often used APIs:
.Setup()
.Verifiable()
.Callback()
.Returns()
.Throws()
It.Is<type>(x => condition)
JustMock
Use the Visual Studio NuGet package manager
Two versions:
Free version (constrained )
Paid version (unconstrained )
JustMock syntax
The most often used APIs:
.CallOriginal()
.Returns()
.DoInstead()
.DoNothing()
.Throw()
Arg.Matches<type>(x => condition)
Constrained
FakeItEasy
nSubstitute
RhinoMocks
Unconstrained