Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6063607
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T09:11:06+00:00 2026-05-23T09:11:06+00:00

I thought I’d attempt a code kata that simulates an ATM machine on the

  • 0

I thought I’d attempt a code kata that simulates an ATM machine on the command line. I decided to drive the design using TDD. I’ve run into an interesting scenario and I’m curious about what others have done in this scenario.

If you look (down at the bottom) at my AtmMachine class, you’ll notice that I’m exiting my while loop on purpose so that my tests don’t time out. This feels like a code smell to me and I’d like to know if others do things like this.

My current feelings are split betweeen:

  1. “I’m doing it wrong” by attempting to unit test ongoing execution
  2. The inability to write a unit test for it implies that “while” is the wrong construct

Here are the unit tests that I have for the atm machine so far:

[TestClass]
public class when_atm_starts
{
    private static readonly string WELCOME_MSG = "Welcome to Al Banco de Ruiz!";

    private AtmMachine _atm;
    private Mock<IAtmInput> _inputMock;
    private Mock<IAtmOutput> _outputMock;
    private Mock<ILogger> _loggerMock;
    private Mock<ICommandFactory> _cmdFactoryMock;


    [TestInitialize]
    public void BeforeEachTest()
    {
        _inputMock = new Mock<IAtmInput>();
        _outputMock = new Mock<IAtmOutput>();
        _loggerMock = new Mock<ILogger>();
        _cmdFactoryMock = new Mock<ICommandFactory>();

        _atm = new AtmMachine(_inputMock.Object, _outputMock.Object, _loggerMock.Object, _cmdFactoryMock.Object);
    }


    [TestMethod]
    public void no_one_should_be_logged_in()
    {
        this.SetupForCancelledUser();

        _atm.Start();

        Assert.IsNull(_atm.CurrentUser);
    }

    [TestMethod]
    public void should_print_welcome_to_output()
    {
        this.SetupForCancelledUser();

        _atm.Start();

        _outputMock.Verify(o => o.Write(WELCOME_MSG));
    }

    [TestMethod]
    public void should_execute_login_command()
    {
        Mock<ILoginCommand> loginCmdMock = new Mock<ILoginCommand>();

        _cmdFactoryMock.Setup(cf => cf.GetLoginCommand(_inputMock.Object, _outputMock.Object))
            .Returns(loginCmdMock.Object);

        loginCmdMock.Setup(lc => lc.LogonUser())
            .Returns(AtmUser.CancelledUser);

        _atm.Start();

        loginCmdMock.Verify(lc => lc.LogonUser());
    }


    private void SetupForCancelledUser()
    {
        Mock<ILoginCommand> loginCmdMock = new Mock<ILoginCommand>();

        _cmdFactoryMock.Setup(cf => cf.GetLoginCommand(_inputMock.Object, _outputMock.Object))
            .Returns(loginCmdMock.Object);

        loginCmdMock.Setup(lc => lc.LogonUser())
            .Returns(AtmUser.CancelledUser);
    }
}

And here is the corresponding AtmMachine class.

public class AtmMachine
{
    public static readonly string WELCOME_MSG = "Welcome to Al Banco de Ruiz!";


    private bool _shouldContinue;
    private ILogger _log;
    private ICommandFactory _cmdFactory;
    private IAtmInput _input;
    private IAtmOutput _output;


    public object CurrentUser { get; set; }


    public AtmMachine(
        IAtmInput input,
        IAtmOutput output,
        ILogger logger,
        ICommandFactory cmdFactory)
    {
        this._input = input;
        this._output = output;
        this._log = logger;
        this._cmdFactory = cmdFactory;
    }


    public void Start()
    {
        _shouldContinue = true;

        while (_shouldContinue)
        {
            _output.Clear();
            _output.Write(WELCOME_MSG);
            AtmUser user = this.GetNextUser();

            if (user == AtmUser.CancelledUser) { _shouldContinue = false; }

            _shouldContinue = false;
        }
    }


    private AtmUser GetNextUser()
    {
        ILoginCommand loginCmd = _cmdFactory.GetLoginCommand(_input, _output);
        return loginCmd.LogonUser();
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T09:11:06+00:00Added an answer on May 23, 2026 at 9:11 am

    You’re correct about testing the loop in that way. I don’t have much context around the functionality your trying to test drive other than “no one logged in”, so I’ll take some liberties on my suggestions.

    Firstly, for the loop testing, you can do it a couple of ways, depending on your preference. the first way is to extract the loop condition into a method that can be overridden in a subclass used for testing.

    // In your AtmMachine
    public void Start()
    {
        _shouldContinue = true;
    
        while (stillRunning())
        {
            // Do some ATM type stuff
        }
    }
    
    protected virtual bool stillRunning() {
        return _shouldContinue;
    }
    

    Inside your test you can create a special test class that overrides stillRunning().

    // Inside your test
    [TestMethod]
    public void no_one_should_be_logged_in()
    {
        _atm = new AtmThatImmediatelyShutsDown();
    
        this.SetupForCancelledUser();
    
        _atm.Start();
    
        Assert.IsNull(_atm.CurrentUser);
    }
    
    class AtmThatImmediatelyShutsDown : AtmMachine {
        protected override bool stillRunning() {
            return false;
        }
    }
    

    Another option is to inject the condition as an class/interface that can be mocked. The choice is yours.

    Secondly, for simplicity sake, I would extract the guts of that loop into a method with increased visibility to allow for testing of the code in the loop.

    // In your AtmMachine
    public void Start()
    {
        _shouldContinue = true;
    
        while (stillRunning())
        {
            processCommands();
        }
    }
    
    public void processCommands() {
        ...
    }
    

    Now, you can directly call the processCommands() method and skip all of the looping.

    Hope that helps!

    Brandon

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.