Home > Net >  Unittest would not run my mock and still asks for an input
Unittest would not run my mock and still asks for an input

Time:04-03

I have a simple ATM stimulating function in Pycharm and want to write tests for my functions. However every time I run my test on the first function asking for a User Pin, the terminal asks me for an input instead of running the mock. Here is my function:

def validate_pin(correct_pin):
    pin_input = input('PLEASE ENTER YOUR 4-DIGIT PIN: ')
    if pin_input.isnumeric() is True and int(pin_input) == correct_pin:
        return True
    return False


def calculate_balance(current_balance):
    withdraw_amount = input("Please enter the amount you would like to withdraw: ")
    if withdraw_amount.isnumeric() is not True:
        raise TypeError
    new_balance = current_balance - int(withdraw_amount)
    if new_balance < 0:
        raise Exception
    return new_balance


def withdraw_money():
    correct_pin = 1223
    attempts = 3
    balance = 100

    while attempts != 0:
        pin_validity = validate_pin(correct_pin)

        if pin_validity is True:
            print('PIN is correct.')
            try:
                new_balance = calculate_balance(balance)
            except TypeError:
                print("Please enter numbers only!")
            except Exception:
                print("You have put an unaccepted amount! Try again later.")
            else:
                print("You have £{} remaining in your account.".format(new_balance))
            finally:
                print("☻☻☻ THANK YOU FOR USING THIS ATM. HAVE A GOOD DAY! ☻☻☻")
            break

        else:
            attempts -= 1
            print("Wrong pin, try again! You only have {} attempts remaining.".format(attempts))


withdraw_money()

I have tried different versions of syntax to run the tests, non of which works ... Any thoughts?

1.

import unittest
from unittest.mock import patch
import atm
from unittest import TestCase


class TestingVersionThree(unittest, TestCase):

    @patch('builtins.input', lambda *args: '1223')
    def test_func1(self):
        self.assertEqual(atm.validate_pin(), True)

    @patch('builtins.input', lambda *args: '1111')
    def test_func2(self):
        self.assertEqual(atm.validate_pin(), False)


if __name__ == '__main__':
    unittest.main()
class TestPinMockedInput(unittest.TestCase):

    @patch('builtins.input', lambda x: "1223")
    def test_with_valid_input(self):
        result = atm.validate_pin()
        expected_result = True
        self.assertTrue(result == expected_result)

    @patch('builtins.input', lambda x: "1111")
    def test_invalid_input_wrong_number(self):
        with self.assertRaises(ValueError):
            result = atm.validate_pin()
            expected_result = False
            self.assertTrue(result == expected_result)

    @patch('builtins.input', lambda x: "hi12")
    def test_invalid_input_non_numeric(self):
        with self.assertRaises(ValueError):
            result = atm.validate_pin()
            expected_result = False
            self.assertTrue(result == expected_result)


if __name__ == '__main__':
    unittest.main()

CodePudding user response:

When a Python file is imported, any code that is not in a function is executed. That means anything that is not indented is run.

When the unit test file does import atm it will end up running the withdraw_money() function call that is at the bottom of atm.py.

The statement in file 2, if __name__ == "__main__":, is the way of allowing the function to be executed if the file is run from the command line, but prevents the function being called if it is imported from another module.

  • Related