Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "errors"
- "fmt"
- "testing"
- "github.com/stretchr/testify/require"
- )
- // TestPolymorphism tests treating a savings account like a basic account
- func TestPolymorphism(t *testing.T) {
- savingsAccount, err := NewSavingsAccount("mysavings")
- require.NoError(t, err)
- require.NotNil(t, savingsAccount)
- savingsAccount.SetWithdrawalLimit(4.0)
- // Treat the savings account as a basic bank account
- basicAccount := BankAccount(savingsAccount)
- b1, err := basicAccount.Balance()
- require.NoError(t, err)
- require.Equal(t, 0.0, b1)
- require.NoError(t, basicAccount.Deposit(12.0))
- b2, err := basicAccount.Balance()
- require.NoError(t, err)
- require.Equal(t, 12.0, b2)
- require.Error(t, basicAccount.Withdraw(5.0))
- require.NoError(t, basicAccount.Withdraw(4.0))
- b3, err := basicAccount.Balance()
- require.NoError(t, err)
- require.Equal(t, 8.0, b3)
- }
- // BankAccount represents a bank account
- type BankAccount interface {
- // Balance returns the current balance of the account
- Balance() (float64, error)
- // Deposit deposits money onto the account
- Deposit(value float64) error
- // Withdraw widthdraws money from the account
- Withdraw(value float64) error
- }
- // SavingsAccount represents a savings bank account
- type SavingsAccount interface {
- // Embedded public interface
- BankAccount
- // SetWithdrawalLimit sets a new withdrawal limit
- SetWithdrawalLimit(newLimit float64) error
- }
- /*************************************************\
- BASIC BANK ACCOUNT
- \*************************************************/
- // NewBankAccount creates a new bank account instance
- func NewBankAccount(id string) (BankAccount, error) {
- return newBankAccount(id)
- }
- func newBankAccount(id string) (*bankAccount, error) {
- if len(id) < 1 {
- return nil, errors.New("invalid bank account id")
- }
- return &bankAccount{
- id: id,
- blocked: false,
- balance: 0,
- }, nil
- }
- type bankAccount struct {
- // Private fields
- id string
- blocked bool
- balance float64
- }
- func (ba *bankAccount) checkBlocked() error {
- if ba.blocked {
- return fmt.Errorf("account %s is blocked", ba.id)
- }
- return nil
- }
- func (ba *bankAccount) Balance() (float64, error) {
- if err := ba.checkBlocked(); err != nil {
- return 0, err
- }
- return ba.balance, nil
- }
- func (ba *bankAccount) Deposit(value float64) error {
- if err := ba.checkBlocked(); err != nil {
- return err
- }
- if value > 0 {
- ba.balance += value
- return nil
- }
- return fmt.Errorf("invalid deposit value: %f", value)
- }
- func (ba *bankAccount) Withdraw(value float64) error {
- if err := ba.checkBlocked(); err != nil {
- return err
- }
- if ba.balance-value < 0 {
- return errors.New("insufficient funds")
- }
- ba.balance -= value
- return nil
- }
- // TestBankAccount tests BankAccount
- func TestBankAccount(t *testing.T) {
- account, err := NewBankAccount("ABC")
- require.NoError(t, err)
- require.NotNil(t, account)
- b1, err := account.Balance()
- require.NoError(t, err)
- require.Equal(t, 0.0, b1)
- require.NoError(t, account.Deposit(4.5))
- b2, err := account.Balance()
- require.NoError(t, err)
- require.Equal(t, 4.5, b2)
- require.NoError(t, account.Withdraw(2.5))
- b3, err := account.Balance()
- require.NoError(t, err)
- require.Equal(t, 2.0, b3)
- }
- /*************************************************\
- SAVINGS BANK ACCOUNT
- - composes a basic account
- - overwrites method Withdraw
- \*************************************************/
- // NewSavingsAccount creates a new savings bank account instance
- func NewSavingsAccount(id string) (SavingsAccount, error) {
- return newSavingsAccount(id)
- }
- func newSavingsAccount(id string) (*savingsAccount, error) {
- newBankAccount, err := newBankAccount(id)
- if err != nil {
- return nil, err
- }
- return &savingsAccount{
- bankAccount: newBankAccount,
- withdrawalLimit: 0.0,
- }, nil
- }
- type savingsAccount struct {
- // Embedded private struct
- *bankAccount
- // Private fields
- withdrawalLimit float64
- }
- func (ba *savingsAccount) Withdraw(value float64) error {
- if value > ba.withdrawalLimit {
- return fmt.Errorf("withdrawal limit (%f) exceeded", ba.withdrawalLimit)
- }
- return ba.bankAccount.Withdraw(value)
- }
- func (ba *savingsAccount) SetWithdrawalLimit(newLimit float64) error {
- if newLimit < 0 {
- return fmt.Errorf("invalid withdrawal limit: %f", newLimit)
- }
- ba.withdrawalLimit = newLimit
- return nil
- }
- // TestSavingsAccount tests SavingsAccount
- func TestSavingsAccount(t *testing.T) {
- account, err := NewSavingsAccount("mysavings")
- require.NoError(t, err)
- require.NotNil(t, account)
- b1, err := account.Balance()
- require.NoError(t, err)
- require.Equal(t, 0.0, b1)
- require.NoError(t, account.Deposit(12.0))
- b2, err := account.Balance()
- require.NoError(t, err)
- require.Equal(t, 12.0, b2)
- account.SetWithdrawalLimit(4.0)
- require.Error(t, account.Withdraw(5.0))
- require.NoError(t, account.Withdraw(4.0))
- b3, err := account.Balance()
- require.NoError(t, err)
- require.Equal(t, 8.0, b3)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement