Step 3 - Interacting with objects
Response setup
Okay, so we have a basic withdraw
method for our Atm class. It's a good start. Now, if we have a look at the requirements we initially got from our client, we see that a successful withdraw should generate a response in the form of a Hash.The user story for the response is:
This hash is the equivalent of a receipt that the Atm prints out in the real life. It should look like this if the transaction was successful:
For unsuccessful transactions, it should look like this:
Let's break this down.
status
Can be
true
orfalse
depending if the transaction was successful.
message
A message to the user. We can set that to
success
when the transaction was successful and to something else if we for some reason can not perform the transaction.
date
The date of the transaction - simply today's date.
amount
Visible only when transaction was successful.
Simply the amount that was withdrawn.
bills
Visible only when transaction was successful.
An array of bills that was dispatched by the ATM. This symbolize the actual cash you would get in real life.
Testing the happy path
The first test we will write is the so called "Happy Path". We know that a transaction can either be successful or rejected for some reason. We'll get back to the rejections (that is the lion-share of the work that lies ahead of us). At this stage, let's focus on a simple successful transaction.
Let's start with preparing our test.
The ATM needs to interact with another class - we will call it Account
. The Account class will symbolize both the bank account and a card we can use in the ATM (there is no need to create both an Account class and a Card class for the sake of this prototype).
However, we have not created that class yet, so in out atm_spec
we will use a so called instance_double
in order to be able to test the functionality. Doubles are objects that can be used as stand-ins for instances of other classes (hence the name instance_double
). Even if they still are not defined (as in our case). We will go over doubles more extensively further down the road in the camp. You can think of doubles as "fake" objects that we use for testing. We don't want to build the Account
class yet, so we'll just make a fake one for now.
Let's define a class_double
in our spec and give it a name of account
. We'll give our account
a @balance
of 100
. Then we'll be able to use this in our testing.
!FILENAME spec/atm_spec.rb
Okay, we want the withdraw
method to have access to the account
object in order to know things about it. Things like a balance
for instance, right? The ATM needs to know if there are enough funds in the account before it clears the transaction.
First we will write a test and then we will modify the implementation code.
Note: Make sure that you read the comments in the it
block below but do not include them in your spec.
!FILENAME spec/atm_spec.rb
Now, make sure you run this spec and study the error messages from Rspec carefully.
In order to make this pass, we need to modify the withdraw
method in our implementation code. Again, be mindful of the comments in the code below.
!FILENAME spec/atm_spec.rb
Run your specs again.
Note that your first spec, the one that was passing just a moment ago is failing now. The error message tells you that you have passed in 1 argument but the method expects 2. Why is that?
Well, we have modified the withdraw
method since we wrote that first spec. Not the method is expecting the account
object as well as the amount we want to withdraw to be passed in as arguments. So we need to modify that spec and add account as an argument. (See the modified expect
statement below).
!FILENAME spec/atm_spec.rb
Now, everything should go green when you run your tests.
Last updated