-
Notifications
You must be signed in to change notification settings - Fork 15
IoC Support
Chris Peterson edited this page Sep 23, 2018
·
2 revisions
IoC tests require an additional package:
PM> Install-Package Kekiri.IoC.Autofac
Consider this collection of classes:
class Orchestrator {
public Validator Validator { get; private set; }
public Executor Executor { get; private set; }
public IDataComponent DataComponent { get; private set; }
public Orchestrator(
Validator validator, Executor executor, IDataComponent dataComponent) {
Validator = validator;
Executor = executor;
DataComponent = dataComponent;
}
public int Process() {
var data = DataComponent.GetData();
Validator.Validate(data);
return Executor.Execute(data);
}
}
class Validator {
public void Validate(string input) {
if (string.IsNullOrEmpty(input)) {
throw new ArgumentException("Must have a value", "input");
}
}
}
class Executor {
public WordCounter WordCounter { get; set; }
public Executor(WordCounter wordCounter) {
WordCounter = wordCounter;
}
public int Execute(string input) {
return WordCounter.CountWords(input);
}
}
class WordCounter {
public int CountWords(string sentence) {
return sentence.Split(' ').Length;
}
}
interface IDataComponent {
string GetData();
}
class RealDataComponent : IDataComponent
{
public string GetData() {
using (var connection = new SqlConnection("[YourDatabase]")) {
connection.Open();
using (var command = connection.CreateCommand()) {
command.CommandText = "SELECT YourField from [YourTable]";
return (string)command.ExecuteScalar();
}
}
}
}
class FakeDataComponent : IDataComponent
{
public string GetData() {
return "all your base are belong to us";
}
}
And this test fixture:
public class Orchestrator_scenarios : ExampleScenarios
{
Orchestrator _orchestrator;
[Scenario]
public void Using_fakes_with_autofac()
{
Given(explicitly_registered_fake_data_access);
When(resolving_an_instance);
Then(It_uses_reals_for_everything)
.But(data_access_object_is_fake)
.And(it_computes_the_right_result);
}
void explicitly_registered_fake_data_access() {
Container.Register(new FakeDataComponent());
}
void resolving_an_instance() {
_orchestrator = Container.Resolve<Orchestrator>();
}
void It_uses_reals_for_everything() {
Assert.IsType<Validator>(_orchestrator.Validator);
Assert.IsType<Executor>(_orchestrator.Executor);
Assert.IsType<WordCounter>(_orchestrator.Executor.WordCounter);
}
void data_access_object_is_fake() {
Assert.IsType<FakeDataComponent>(_orchestrator.DataComponent);
}
void it_computes_the_right_result() {
Assert.Equal(7, _orchestrator.Process());
}
}
When calling Container.Resolve
a full object graph is created for _orchestrator
. Unless explicitly registered into the IoC Container
, real objects are used!
This approach maximizes the code under test, i.e. only the outermost seams are mocked/faked.