1

I have class, which is using Console class and sets this variables in constructor.

  public Scene() {
        Height = Console.WindowHeight;
        Width = Console.WindowWidth;
    } 

and test class, which tests this constructor:

public class SceneTests {
    [Fact]
    public void Contructor_None_ShouldReturnScene() {
        var testScene = new Scene();
        Assert.Equal(Console.WindowHeight, testScene.Height);
        Assert.Equal(Console.WindowWidth, testScene.Width);
    }
}

But while running this test I've got Exeption:

Exception has occurred: CLR/System.IO.IOException
An exception of type 'System.IO.IOException' occurred in System.Console.dll but was not handled in user code: 'Nieprawidłowe dojście'
at System.ConsolePal.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
at System.ConsolePal.get_WindowHeight()
at System.Console.get_WindowHeight()

I guess, that's because I don't have actual Console window.

Can I somehow simulate that? Maybe simple creating buffer manually and adding it to Console will solve the problem.

Morasiu
  • 1,204
  • 2
  • 16
  • 38
  • What's the type of the project? Did you try to change it to Console Application? – Nekeniehl Jan 07 '19 at 15:38
  • Check this [thread](https://stackoverflow.com/questions/5852862/mocking-system-console-behaviour) to see how it could be resolved – vhr Jan 07 '19 at 15:39
  • What do you mean? It's ClassLib if you ask about that. – Morasiu Jan 07 '19 at 15:39
  • 4
    You handle this the same way you handle IoC anywhere else. You code against an abstraction instead of a concrete implementation. Right now you have a hard dependency on System.Console. So the solution is to write a wrapper around System.Console and then create an interface for that wrapper to inherit from. Then in your unit test, you can mock that interface. Of course, it's likely someone else has run into this before, and therefore made an abstraction and wrapper already. There is one for [System.IO](https://github.com/System-IO-Abstractions/System.IO.Abstractions). – mason Jan 07 '19 at 15:47

1 Answers1

5

In the normal fashion...

Create an interface that describes your access to the console. Implement that interface in a class that simply uses the System.Console. Inject that into your running code using your favorite "Dependency Injection" mechanism.

Then create another class for use during testing that implements that same interface, but without using the System.Console class (for example, simply hard-code the WindowHeight and WindowWidth properties, have Console.ReadLine always return the same string, write Console.Write or WriteLine to some other place). Inject that class into your unit test code.

Flydog57
  • 6,851
  • 2
  • 17
  • 18