SHARE
TWEET

Untitled

a guest Jun 16th, 2019 65 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package main
  2.  
  3. import (
  4.     "errors"
  5.     "fmt"
  6.     "testing"
  7.  
  8.     "github.com/stretchr/testify/require"
  9. )
  10.  
  11. // TestPolymorphism tests treating a savings account like a basic account
  12. func TestPolymorphism(t *testing.T) {
  13.     savingsAccount, err := NewSavingsAccount("mysavings")
  14.     require.NoError(t, err)
  15.     require.NotNil(t, savingsAccount)
  16.  
  17.     savingsAccount.SetWithdrawalLimit(4.0)
  18.  
  19.     // Treat the savings account as a basic bank account
  20.     basicAccount := BankAccount(savingsAccount)
  21.  
  22.     b1, err := basicAccount.Balance()
  23.     require.NoError(t, err)
  24.     require.Equal(t, 0.0, b1)
  25.  
  26.     require.NoError(t, basicAccount.Deposit(12.0))
  27.  
  28.     b2, err := basicAccount.Balance()
  29.     require.NoError(t, err)
  30.     require.Equal(t, 12.0, b2)
  31.  
  32.     require.Error(t, basicAccount.Withdraw(5.0))
  33.  
  34.     require.NoError(t, basicAccount.Withdraw(4.0))
  35.  
  36.     b3, err := basicAccount.Balance()
  37.     require.NoError(t, err)
  38.     require.Equal(t, 8.0, b3)
  39. }
  40.  
  41. // BankAccount represents a bank account
  42. type BankAccount interface {
  43.     // Balance returns the current balance of the account
  44.     Balance() (float64, error)
  45.  
  46.     // Deposit deposits money onto the account
  47.     Deposit(value float64) error
  48.  
  49.     // Withdraw widthdraws money from the account
  50.     Withdraw(value float64) error
  51. }
  52.  
  53. // SavingsAccount represents a savings bank account
  54. type SavingsAccount interface {
  55.     // Embedded public interface
  56.     BankAccount
  57.  
  58.     // SetWithdrawalLimit sets a new withdrawal limit
  59.     SetWithdrawalLimit(newLimit float64) error
  60. }
  61.  
  62. /*************************************************\
  63.   BASIC BANK ACCOUNT
  64. \*************************************************/
  65.  
  66. // NewBankAccount creates a new bank account instance
  67. func NewBankAccount(id string) (BankAccount, error) {
  68.     return newBankAccount(id)
  69. }
  70.  
  71. func newBankAccount(id string) (*bankAccount, error) {
  72.     if len(id) < 1 {
  73.         return nil, errors.New("invalid bank account id")
  74.     }
  75.     return &bankAccount{
  76.         id:      id,
  77.         blocked: false,
  78.         balance: 0,
  79.     }, nil
  80. }
  81.  
  82. type bankAccount struct {
  83.     // Private fields
  84.     id      string
  85.     blocked bool
  86.     balance float64
  87. }
  88.  
  89. func (ba *bankAccount) checkBlocked() error {
  90.     if ba.blocked {
  91.         return fmt.Errorf("account %s is blocked", ba.id)
  92.     }
  93.     return nil
  94. }
  95.  
  96. func (ba *bankAccount) Balance() (float64, error) {
  97.     if err := ba.checkBlocked(); err != nil {
  98.         return 0, err
  99.     }
  100.     return ba.balance, nil
  101. }
  102.  
  103. func (ba *bankAccount) Deposit(value float64) error {
  104.     if err := ba.checkBlocked(); err != nil {
  105.         return err
  106.     }
  107.     if value > 0 {
  108.         ba.balance += value
  109.         return nil
  110.     }
  111.     return fmt.Errorf("invalid deposit value: %f", value)
  112. }
  113.  
  114. func (ba *bankAccount) Withdraw(value float64) error {
  115.     if err := ba.checkBlocked(); err != nil {
  116.         return err
  117.     }
  118.     if ba.balance-value < 0 {
  119.         return errors.New("insufficient funds")
  120.     }
  121.     ba.balance -= value
  122.     return nil
  123. }
  124.  
  125. // TestBankAccount tests BankAccount
  126. func TestBankAccount(t *testing.T) {
  127.     account, err := NewBankAccount("ABC")
  128.     require.NoError(t, err)
  129.     require.NotNil(t, account)
  130.  
  131.     b1, err := account.Balance()
  132.     require.NoError(t, err)
  133.     require.Equal(t, 0.0, b1)
  134.  
  135.     require.NoError(t, account.Deposit(4.5))
  136.  
  137.     b2, err := account.Balance()
  138.     require.NoError(t, err)
  139.     require.Equal(t, 4.5, b2)
  140.  
  141.     require.NoError(t, account.Withdraw(2.5))
  142.  
  143.     b3, err := account.Balance()
  144.     require.NoError(t, err)
  145.     require.Equal(t, 2.0, b3)
  146. }
  147.  
  148. /*************************************************\
  149.   SAVINGS BANK ACCOUNT
  150.     - composes a basic account
  151.     - overwrites method Withdraw
  152. \*************************************************/
  153.  
  154. // NewSavingsAccount creates a new savings bank account instance
  155. func NewSavingsAccount(id string) (SavingsAccount, error) {
  156.     return newSavingsAccount(id)
  157. }
  158.  
  159. func newSavingsAccount(id string) (*savingsAccount, error) {
  160.     newBankAccount, err := newBankAccount(id)
  161.     if err != nil {
  162.         return nil, err
  163.     }
  164.  
  165.     return &savingsAccount{
  166.         bankAccount:     newBankAccount,
  167.         withdrawalLimit: 0.0,
  168.     }, nil
  169. }
  170.  
  171. type savingsAccount struct {
  172.     // Embedded private struct
  173.     *bankAccount
  174.  
  175.     // Private fields
  176.     withdrawalLimit float64
  177. }
  178.  
  179. func (ba *savingsAccount) Withdraw(value float64) error {
  180.     if value > ba.withdrawalLimit {
  181.         return fmt.Errorf("withdrawal limit (%f) exceeded", ba.withdrawalLimit)
  182.     }
  183.     return ba.bankAccount.Withdraw(value)
  184. }
  185.  
  186. func (ba *savingsAccount) SetWithdrawalLimit(newLimit float64) error {
  187.     if newLimit < 0 {
  188.         return fmt.Errorf("invalid withdrawal limit: %f", newLimit)
  189.     }
  190.     ba.withdrawalLimit = newLimit
  191.     return nil
  192. }
  193.  
  194. // TestSavingsAccount tests SavingsAccount
  195. func TestSavingsAccount(t *testing.T) {
  196.     account, err := NewSavingsAccount("mysavings")
  197.     require.NoError(t, err)
  198.     require.NotNil(t, account)
  199.  
  200.     b1, err := account.Balance()
  201.     require.NoError(t, err)
  202.     require.Equal(t, 0.0, b1)
  203.  
  204.     require.NoError(t, account.Deposit(12.0))
  205.  
  206.     b2, err := account.Balance()
  207.     require.NoError(t, err)
  208.     require.Equal(t, 12.0, b2)
  209.  
  210.     account.SetWithdrawalLimit(4.0)
  211.  
  212.     require.Error(t, account.Withdraw(5.0))
  213.  
  214.     require.NoError(t, account.Withdraw(4.0))
  215.  
  216.     b3, err := account.Balance()
  217.     require.NoError(t, err)
  218.     require.Equal(t, 8.0, b3)
  219. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top