Abstracting a third-party class

If we tried to test right now, the application would hit the first ReadLine call and the test would time out. Console has the ability to redirect the input and output, but we are not going to use this feature, because it is specific to Console and we want to demonstrate a more generic solution that you can apply anywhere.

What we need is a class that gives us a similar interface to Console. Then we can dependency inject our class for the tests and a thin wrapper for the production code. Let's test drive that interface now.

In the file InputOutputTests.cs:

public class InputOutputTests
{
[Fact]
public void ItExists()
{
var inout = new MockInputOutput();
}
}

In the file ReadLineTests.cs:

public class ReadLineTests
{
[Fact]
public void ItCanBeReadFrom()
{
var inout = new MockInputOutput();
inout.InFeed.Enqueue("Test");

// Act
var input = inout.ReadLine();
}

[Fact]
public void ProvidedInputCanBeRetrieved()
{
// Arrange
var inout = new MockInputOutput();
inout.InFeed.Enqueue("Test");

// Act
var input = inout.ReadLine();

// Assert
Assert.Equal("Test", input);
}

[Fact]
public void ProvidedInputCanBeRetrievedInSuccession()
{
// Arrange
var inout = new MockInputOutput();
inout.InFeed.Enqueue("Test 1");
inout.InFeed.Enqueue("Test 2");

// Act
var input1 = inout.ReadLine();
var input2 = inout.ReadLine();

// Assert
Assert.Equal("Test 1", input1);
Assert.Equal("Test 2", input2);
}
}

In the file ReadTests.cs:

public class ReadTests
{
[Fact]
public void ItCanBeReadFrom()
{
var inout = new MockInputOutput();
inout.InFeed.Enqueue("T");

// Act
var input = inout.Read();
}

[Fact]
public void ProvidedInputCanBeRetrieved()
{
// Arrange
var inout = new MockInputOutput();
inout.InFeed.Enqueue("T");

// Act
var input = inout.Read();

// Assert
Assert.Equal('T', input);
}

[Fact]
public void ProvidedInputCanBeRetrievedInSuccession()
{
// Arrange
var inout = new MockInputOutput();
inout.InFeed.Enqueue("T");
inout.InFeed.Enqueue("E");

// Act
var input1 = inout.Read();
var input2 = inout.Read();

// Assert
Assert.Equal('T', input1);
Assert.Equal('E', input2);
}
}

In the file WriteTests.cs:

public class WriteTests
{
[Fact]
public void ItCanBeWrittenTo()
{
var inout = new MockInputOutput();

// Act
inout.Write("Text");
}

[Fact]
public void WrittenTextCanBeRetrieved()
{
// Arrange
var inout = new MockInputOutput();
inout.Write("Text");

// Act
var writtenText = inout.OutFeed;

// Assert
Assert.Single(writtenText);
Assert.Equal("Text", writtenText.First());
}
}

In the file WriteLineTests.cs:

public class WriteLineTests
{
[Fact]
public void ItCanBeWrittenTo()
{
var inout = new MockInputOutput();

// Act
inout.WriteLine("Text");
}

[Fact]
public void WrittenTextCanBeRetrieved()
{
// Arrange
var inout = new MockInputOutput();
inout.WriteLine("Text");

// Act
var writtenText = inout.OutFeed;

// Assert
Assert.Single(writtenText);
Assert.Equal("Text" + Environment.NewLine, writtenText.First());
}
}

In the file IInputOutput.cs:

public interface IInputOutput
{
void Write(string text);
void WriteLine(string text);
char Read();
string ReadLine();
}

In the file MockInputOutput.cs:

public class MockInputOutput : IInputOutput
{
public List<string> OutFeed { get; set; }
public Queue<string> InFeed { get; set; }

public MockInputOutput()
{
OutFeed = new List<string>();
InFeed = new Queue<string>();
}

public void Write(string text)
{
OutFeed.Add(text);
}

public void WriteLine(string text)
{
OutFeed.Add(text + Environment.NewLine);
}

public char Read()
{
return InFeed.Dequeue().ToCharArray().First();
}

public string ReadLine()
{
return InFeed.Dequeue();
}
}

That handles our mock input and output, but we need to create the production wrapper class for Console, and we need to use Program.cs to inject that class into the Mastermind class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.111.41