From Ch10 of Head First Design Patterns.
Problem: I have a WindowsCE device which every now and again gets into an unknown state due to connetions lost/something strange happening in the field.
Solution: Implement a state machine pattern to make sure these cases are handled correctly
http://stackoverflow.com/questions/8264314/windows-forms-simple-state-machine
namespace GumballState {
class Program {
static void Main(string[] args) {
new GumballMachine();
}
}
enum StateType {
SOLD_OUT = 0,
NO_QUARTER = 1,
HAS_QUARTER = 2,
SOLD = 3
}
class GumballMachine {
//created an instance variable to hold the state values
private int state = (int)StateType.SOLD_OUT;
public GumballMachine() {
InsertQuarter();
}
void InsertQuarter() {
//conditional code within method to handle each state
if (state == (int)StateType.HAS_QUARTER)
Console.WriteLine("You can't insert another quarter");
if (state == (int)StateType.SOLD_OUT)
Console.WriteLine("You can't insert a quarter, the machine is sold out");
if (state == (int)StateType.SOLD)
Console.WriteLine("Please wait, we're giving you a gumball");
if (state == (int)StateType.NO_QUARTER) {
state = (int)StateType.HAS_QUARTER;
Console.WriteLine("You inserterd a quarter");
}
}
}
}
felt a bit verbose for a simple example.. so using static readonly ints…maybe better private const int (then CAPS would be more ok!)
namespace GumballState {
class Program {
static void Main(string[] args) {
new GumballMachine();
}
}
class GumballMachine {
static readonly int SOLD_OUT = 0;
static readonly int NO_QUARTER = 1;
static readonly int HAS_QUARTER = 2;
static readonly int SOLD = 3;
//created an instance variable to hold the state values
int state = SOLD_OUT;
public GumballMachine() {
InsertQuarter();
}
void InsertQuarter() {
//conditional code within method to handle each state
if (state == HAS_QUARTER)
Console.WriteLine("You can't insert another quarter");
if (state == SOLD_OUT)
Console.WriteLine("You can't insert a quarter, the machine is sold out");
if (state == SOLD)
Console.WriteLine("Please wait, we're giving you a gumball");
if (state == NO_QUARTER) {
state = HAS_QUARTER;
Console.WriteLine("You inserterd a quarter");
}
}
}
}
this is fine
class Program {
static void Main(string[] args) {
new GumballMachine(20);
}
}
public class GumballMachine {
//enums is bigger app.. usually CamelCase
static readonly int SOLD_OUT = 0;
static readonly int NO_QUARTER = 1;
static readonly int HAS_QUARTER = 2;
static readonly int SOLD = 3;
//created an instance variable to hold the state value... could use underscore here.
public int state = SOLD_OUT;
//another instance variable to keep track of number of gumballs in machine
public int currentNumberOfGumballsInMachine = 0;
public GumballMachine(int initialNumberOfGumballsInMachine) {
currentNumberOfGumballsInMachine = initialNumberOfGumballsInMachine;
if (currentNumberOfGumballsInMachine > 0)
state = NO_QUARTER;
}
public string DisplayStatus() {
var x = "Number of Gumballs: " + currentNumberOfGumballsInMachine.ToString();
x += Environment.NewLine;
x += "State: " + state.ToString();
x += Environment.NewLine;
return x;
}
public void InsertQuarter() {
//conditional code within method to handle each state
if (state == HAS_QUARTER)
Console.WriteLine("You can't insert another quarter");
if (state == SOLD_OUT)
Console.WriteLine("You can't insert a quarter, the machine is sold out");
if (state == SOLD)
Console.WriteLine("Please wait, we're giving you a gumball");
if (state == NO_QUARTER) {
state = HAS_QUARTER;
Console.WriteLine("You inserterd a quarter");
}
}
public void EjectQuarter() {
if (state == HAS_QUARTER) {
Console.WriteLine("Quarter returned");
state = NO_QUARTER;
} else
Console.WriteLine("logic error in EjectQuarter");
}
public void TurnCrank() {
if (state == HAS_QUARTER) {
Console.WriteLine("You turned");
state = SOLD;
Dispense();
}
}
public void Dispense() {
if (state == SOLD) {
Console.WriteLine("a gumball comes rolling out of the slot");
currentNumberOfGumballsInMachine -= 1;
if (currentNumberOfGumballsInMachine == 0) {
Console.WriteLine("Out of gumballs");
state = SOLD_OUT;
}
else
state = NO_QUARTER;
}
}
}
and wrapping some smelly testing around it:
[TestFixture]
public class GumballTests {
[Test]
public void MyTestMethod() {
var g = new GumballMachine(3);
var y = g.DisplayStatus();
Console.WriteLine(y);
g.InsertQuarter();
g.TurnCrank();
y = g.DisplayStatus();
Console.WriteLine(y);
//Assert.AreEqual(3, g.currentNumberOfGumballsInMachine);
}
}
not refactored at all.. but goal is to learn about state…
What happens if code changes ie a new feature request – State Pattern
Problem is that now I need to change a lot of my state code.. gets messy and complex very quickly.
So we want something down the road which is easy to maintain.
Each state class is responsible for the behaviour of the ‘gumball machine’ when it is in that state
public class GumballMachine {
IState soldOutState;
IState noQuarterState;
IState hasQuarterState;
IState soldState;
IState state;
int count = 0;
public int Count { get { return count; } }
public GumballMachine(int numberGumballs) {
//creating the state instances - one of each
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
soldOutState = new SoldOutState(this);
this.count = numberGumballs;
if (numberGumballs > 0)
state = noQuarterState;
else
state = soldOutState;
}
public string InsertQuarter() {
return state.InsertQuarter();
}
public string EjectQuarter() {
return state.EjectQuarter();
}
public string TurnCrank() {
return state.TurnCrank() + state.Dispense();
}
public void SetState(IState state) {
this.state = state;
}
public IState GetState() {
return state;
}
public IState GetNoQuarterState() {
return noQuarterState;
}
public IState GetHasQuarterState() {
return hasQuarterState;
}
public IState GetSoldState() {
return soldState;
}
public IState GetSoldOutState() {
return soldOutState;
}
public string ReleaseBall() {
if (count != 0)
count--;
return ("A gumball comes rolling out the slot...\n\n");
}
public string MachineStateHeader() {
var result = new StringBuilder();
result.Append("Mighty Gumball, Inc.");
result.Append("\nC# Enabled Standing Gumball Model #2005\n");
result.Append("Inventory: " + count + " gumball");
if (count != 1) {
result.Append("s");
}
result.Append("\nMachine is " + state.ToString());
return result.ToString();
}
}
public class NoQuarterState : IState {
//a reference to the gumballMachine
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
gumballMachine.SetState(gumballMachine.GetHasQuarterState());
return ("You inserted a quarter");
}
public string EjectQuarter() {
return "You haven't inserted a quarter\n";
}
public string TurnCrank() {
return "You turned but there's no quarter\n";
}
public string Dispense() {
return "You need to pay first\n";
}
public override string ToString() {
return "State: NoQuarter.\n Waiting for quarter\n";
}
}
public class HasQuarterState : IState {
GumballMachine gumballMachine;
//IState soldState;
//Random randomWinner = new Random(System.DateTime.Now.Millisecond);
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
//soldState = new SoldState(gumballMachine);
}
public string InsertQuarter() {
return "You can't insert another quarter\n";
}
public string EjectQuarter() {
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
return "Quarter returned\n";
}
public string TurnCrank() {
string output;
output = "You turned...\n";
//int winner = randomWinner.Next(10);
//if (winner == 0 && gumballMachine.Count > 1) {
// gumballMachine.StateOfMachine = new WinnerState(gumballMachine);
//}
//else {
gumballMachine.SetState(gumballMachine.GetSoldState());
//}
return output;
}
public string Dispense() {
string output;
output = gumballMachine.ReleaseBall();
output += "No gumball dispensed\n";
return output;
}
public override string ToString() {
return "State: HasQuarter\n waiting for turn of crank";
}
}
public class SoldState : IState {
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
return "Please wait, we're already giving you a gumball\n";
}
public string EjectQuarter() {
return "Sorry, you already turned the crank\n";
}
public string TurnCrank() {
return "Turning twice doesn't get you another gumball!\n";
}
public string Dispense() {
string output;
output = gumballMachine.ReleaseBall();
if (gumballMachine.Count > 0) {
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
}
else {
gumballMachine.SetState(gumballMachine.GetSoldOutState());
output += "Oops, out of gumballs!\n";
}
return output;
}
public override string ToString() {
return "State: Sold \n delivering a gumball";
}
}
public class SoldOutState : IState {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
return "You can't insert a quarter, the machine is sold out\n";
}
public string EjectQuarter() {
return "You can't eject, you haven't inserted a quarter yet\n";
}
public string TurnCrank() {
return "Sorry, you already turned the crank\n";
}
public string Dispense() {
string output;
output = gumballMachine.ReleaseBall();
output += "You turned, but there are no gumballs\n";
return output;
}
public override string ToString() {
return "State: SoldOut";
}
}
public interface IState {
string InsertQuarter();
string EjectQuarter();
string TurnCrank();
string Dispense();
}
and tests:
[TestFixture]
public class GumballTests {
[Test]
public void machine_is_in_no_quarter_state_if_has_5_gumballs_to_start_with() {
var gumballMachine = new GumballMachine(5);
Assert.AreEqual(5, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void machine_is_in_sold_out_state_if_has_0_gumballs_to_start_with() {
var gumballMachine = new GumballMachine(0);
Assert.AreEqual(0, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
}
[Test]
public void machine_is_in_has_quarter_state_if_has_5_gumballs_to_start_with_and_person_inserts_quarter() {
var gumballMachine = new GumballMachine(5);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
}
[Test]
public void machine_is_in_no_quarter_state_if_has_5_gumballs_to_start_with_and_person_inserts_quarter_then_ejects() {
var gumballMachine = new GumballMachine(5);
Assert.AreEqual(5, gumballMachine.Count);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
gumballMachine.EjectQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void machine_is_in_no_quarter_state_if_has_5_gumballs_to_start_with_and_person_inserts_quarter_then_turns_crank() {
var gumballMachine = new GumballMachine(5);
Assert.AreEqual(5, gumballMachine.Count);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
//this actually turns crank and dispenses
gumballMachine.TurnCrank();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
Assert.AreEqual(4, gumballMachine.Count);
}
[Test]
public void machine_is_in_sold_out_state_if_has_1_gumball_to_start_with_and_person_inserts_quarter_then_turns_crank() {
var gumballMachine = new GumballMachine(1);
Assert.AreEqual(1, gumballMachine.Count);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
//this actually turns crank and dispenses
gumballMachine.TurnCrank();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
Assert.AreEqual(0, gumballMachine.Count);
}
[Test]
public void machine_gives_correct_message_when_sold_out_and_user_trys_to_insert_a_quarter() {
var gumballMachine = new GumballMachine(0);
var output = gumballMachine.InsertQuarter();
Assert.AreEqual("You can't insert a quarter, the machine is sold out\n", output);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
Assert.AreEqual(0, gumballMachine.Count);
}
[Test]
public void TestGumballMachine() {
GumballMachine gumballMachine = new GumballMachine(5);
StringBuilder gumballMachineOutput = new StringBuilder();
gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
gumballMachineOutput.Append(gumballMachine.InsertQuarter());
gumballMachineOutput.Append(gumballMachine.TurnCrank() + "\n");
//gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
//gumballMachineOutput.Append(gumballMachine.InsertQuarter());
//gumballMachineOutput.Append(gumballMachine.TurnCrank());
//gumballMachineOutput.Append(gumballMachine.InsertQuarter());
//gumballMachineOutput.Append(gumballMachine.TurnCrank() + "\n");
//gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
//gumballMachineOutput.Append(gumballMachine.Refill(5) + "\n");
//gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
//Because of the System.Random object, there is no way to know
//the outcome of the turn of the crank. Therefore, I am writing
//to the console. Use the Console.Out tab of NUnit
Console.WriteLine(gumballMachineOutput.ToString());
}
}
Added in a Winner State, and a refill transition/action.
public class GumballMachine {
IState soldOutState;
IState noQuarterState;
IState hasQuarterState;
IState soldState;
IState winnerState;
IState state;
int count = 0;
public int Count { get { return count; } set { count = value; } }
public GumballMachine(int numberGumballs) {
//creating the state instances - one of each
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
soldOutState = new SoldOutState(this);
winnerState = new WinnerState(this);
this.count = numberGumballs;
if (numberGumballs > 0)
state = noQuarterState;
else
state = soldOutState;
}
public string InsertQuarter() {
return state.InsertQuarter();
}
public string EjectQuarter() {
return state.EjectQuarter();
}
public string TurnCrank() {
var output = state.TurnCrank();
output += state.Dispense();
return output;
}
public string Refill(int i) {
return state.Refill(i);
}
public void SetState(IState state) {
this.state = state;
}
public IState GetState() {
return state;
}
public IState GetNoQuarterState() {
return noQuarterState;
}
public IState GetHasQuarterState() {
return hasQuarterState;
}
public IState GetSoldState() {
return soldState;
}
public IState GetSoldOutState() {
return soldOutState;
}
public IState GetWinnerState() {
return winnerState;
}
public string ReleaseBall() {
if (count != 0)
count--;
return ("A gumball comes rolling out the slot...\n\n");
}
public string MachineStateHeader() {
var result = new StringBuilder();
result.Append("Mighty Gumball, Inc.");
result.Append("\nC# Enabled Standing Gumball Model #2005\n");
result.Append("Inventory: " + count + " gumball");
if (count != 1) {
result.Append("s");
}
result.Append("\nMachine is " + state.ToString());
return result.ToString();
}
}
public class NoQuarterState : IState {
//a reference to the gumballMachine
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
gumballMachine.SetState(gumballMachine.GetHasQuarterState());
return ("You inserted a quarter");
}
public string EjectQuarter() {
return "You haven't inserted a quarter\n";
}
public string TurnCrank() {
return "You turned but there's no quarter\n";
}
public string Dispense() {
return "You need to pay first\n";
}
public override string ToString() {
return "State: NoQuarter.\n Waiting for quarter\n";
}
public string Refill(int i) {
gumballMachine.Count += i;
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
return "filled her up";
}
}
public class HasQuarterState : IState {
GumballMachine gumballMachine;
Random randomWinner = new Random();
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
return "You can't insert another quarter\n";
}
public string EjectQuarter() {
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
return "Quarter returned\n";
}
public string TurnCrank() {
string output;
output = "You turned...\n";
//int winner = randomWinner.Next(10);
//if (winner == 0 && gumballMachine.Count > 1) {
if (gumballMachine.Count == 10) {
gumballMachine.SetState(gumballMachine.GetWinnerState());
}
else {
gumballMachine.SetState(gumballMachine.GetSoldState());
}
return output;
}
public string Dispense() {
string output;
output = gumballMachine.ReleaseBall();
output += "No gumball dispensed\n";
return output;
}
public override string ToString() {
return "State: HasQuarter\n waiting for turn of crank";
}
public string Refill(int numberOfGumball) {
return "Can't refill - there is a quarter in the machine so please turn crank";
}
}
public class SoldState : IState {
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
return "Please wait, we're already giving you a gumball\n";
}
public string EjectQuarter() {
return "Sorry, you already turned the crank\n";
}
public string TurnCrank() {
return "Turning twice doesn't get you another gumball!\n";
}
public string Dispense() {
string output;
output = gumballMachine.ReleaseBall();
if (gumballMachine.Count > 0) {
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
}
else {
gumballMachine.SetState(gumballMachine.GetSoldOutState());
output += "Oops, out of gumballs!\n";
}
return output;
}
public override string ToString() {
return "State: Sold \n delivering a gumball";
}
public string Refill(int numberOfGumball) {
return "Can't refill - you've turned the crank and I'm about to dispense a gumball";
}
}
public class SoldOutState : IState {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
return "You can't insert a quarter, the machine is sold out\n";
}
public string EjectQuarter() {
return "You can't eject, you haven't inserted a quarter yet\n";
}
public string TurnCrank() {
return "Sorry, you already turned the crank\n";
}
public string Dispense() {
string output;
output = gumballMachine.ReleaseBall();
output += "You turned, but there are no gumballs\n";
return output;
}
public override string ToString() {
return "State: SoldOut";
}
public string Refill(int i) {
gumballMachine.Count = i;
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
return "filled her up";
}
}
public class WinnerState : IState {
GumballMachine gumballMachine;
public WinnerState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
public string InsertQuarter() {
return "Please wait, we're already giving you a gumball\n";
}
public string EjectQuarter() {
return "Sorry, you already turned the crank\n";
}
public string TurnCrank() {
return "Turning twice doesn't get you another gumball!\n";
}
public string Dispense() {
string output = "You're a winner. You get 2 gumballs for your quarter";
gumballMachine.ReleaseBall();
if (gumballMachine.Count == 0)
gumballMachine.SetState(gumballMachine.GetSoldOutState());
else {
gumballMachine.ReleaseBall();
if (gumballMachine.Count == 0)
gumballMachine.SetState(gumballMachine.GetSoldOutState());
else
gumballMachine.SetState(gumballMachine.GetNoQuarterState());
}
return output;
}
public string Refill(int numberOfGumball) {
return "Can't refill..you've turned the crank and I'm about to dispense 2 gumballs";
}
}
public interface IState {
string InsertQuarter();
string EjectQuarter();
string TurnCrank();
string Dispense();
string Refill(int numberOfGumball);
}
and tests:
[TestFixture]
public class GumballTests {
[Test]
public void machine_is_in_no_quarter_state_if_has_5_gumballs_to_start_with() {
var gumballMachine = new GumballMachine(5);
Assert.AreEqual(5, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void machine_is_in_sold_out_state_if_has_0_gumballs_to_start_with() {
var gumballMachine = new GumballMachine(0);
Assert.AreEqual(0, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
}
[Test]
public void machine_is_in_has_quarter_state_if_has_5_gumballs_to_start_with_and_person_inserts_quarter() {
var gumballMachine = new GumballMachine(5);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
}
[Test]
public void machine_is_in_no_quarter_state_if_has_5_gumballs_to_start_with_and_person_inserts_quarter_then_ejects() {
var gumballMachine = new GumballMachine(5);
Assert.AreEqual(5, gumballMachine.Count);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
gumballMachine.EjectQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void machine_is_in_no_quarter_state_if_has_5_gumballs_to_start_with_and_person_inserts_quarter_then_turns_crank() {
var gumballMachine = new GumballMachine(5);
Assert.AreEqual(5, gumballMachine.Count);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
//this actually turns crank and dispenses
gumballMachine.TurnCrank();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
Assert.AreEqual(4, gumballMachine.Count);
}
[Test]
public void machine_is_in_sold_out_state_if_has_1_gumball_to_start_with_and_person_inserts_quarter_then_turns_crank() {
var gumballMachine = new GumballMachine(1);
Assert.AreEqual(1, gumballMachine.Count);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
//this actually turns crank and dispenses
gumballMachine.TurnCrank();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
Assert.AreEqual(0, gumballMachine.Count);
}
[Test]
public void machine_gives_correct_message_when_sold_out_and_user_trys_to_insert_a_quarter() {
var gumballMachine = new GumballMachine(0);
var output = gumballMachine.InsertQuarter();
Assert.AreEqual("You can't insert a quarter, the machine is sold out\n", output);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
Assert.AreEqual(0, gumballMachine.Count);
}
[Test]
public void machine_gives_2_gumballs_when_number_in_machine_is_10_faking_a_winner_random_scenario() {
var gumballMachine = new GumballMachine(10);
gumballMachine.InsertQuarter();
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(HasQuarterState)));
var output = gumballMachine.TurnCrank();
StringAssert.Contains("You're a winner", output);
Assert.AreEqual(8, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void machine_goes_to_correct_number_of_gumballs_when_refill_is_done_at_sold_out_state() {
var gumballMachine = new GumballMachine(0);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(SoldOutState)));
var output = gumballMachine.Refill(15);
Assert.AreEqual(15, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void machine_goes_to_correct_number_of_gumballs_when_refill_is_done_on_no_quarter_state() {
var gumballMachine = new GumballMachine(5);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
var output = gumballMachine.Refill(15);
Assert.AreEqual(20, gumballMachine.Count);
Assert.That(gumballMachine.GetState(), Is.TypeOf(typeof(NoQuarterState)));
}
[Test]
public void TestGumballMachine() {
GumballMachine gumballMachine = new GumballMachine(5);
StringBuilder gumballMachineOutput = new StringBuilder();
gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
gumballMachineOutput.Append(gumballMachine.InsertQuarter());
gumballMachineOutput.Append(gumballMachine.TurnCrank() + "\n");
//gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
//gumballMachineOutput.Append(gumballMachine.InsertQuarter());
//gumballMachineOutput.Append(gumballMachine.TurnCrank());
//gumballMachineOutput.Append(gumballMachine.InsertQuarter());
//gumballMachineOutput.Append(gumballMachine.TurnCrank() + "\n");
//gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
//gumballMachineOutput.Append(gumballMachine.Refill(5) + "\n");
//gumballMachineOutput.Append(gumballMachine.MachineStateHeader() + "\n");
//Because of the System.Random object, there is no way to know
//the outcome of the turn of the crank. Therefore, I am writing
//to the console. Use the Console.Out tab of NUnit
Console.WriteLine(gumballMachineOutput.ToString());
}
}