Advertisement
Guest User

Untitled

a guest
Jun 16th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.81 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement