joe
joe

Reputation: 9494

patch my function to random randint function

I have a function to generate sms_token. It must not duplicate with the existing one in the database. However, the space of token might not so big enough then the collision of the newer one might happen.

Python 3.7.0

from random import randint

from multy_herr.user_profiles.models import UserProfile


def rand_six():
    """
    Must find the `sms_token` which no `UserProfile`
    :return:
    """
    tmp = ""
    for i in range(6):
        tmp += str(randint(0, 9))
    if 0 == UserProfile.objects.filter(sms_token=tmp).count():
        return tmp
    else:
        return rand_six()

Therefore I wants to make side_effect of randint to return me the deterministic values by this order 123456, 123456, 111222

With given values. I will be able to test else logic in my rand_six

I had tried this answer, but does not work. rand_six() still return me the original function not the fake one I made.

from unittest.mock import patch
from multy_herr.users.utils import rand_six

    @patch('random.randint')
    def test_rand_six(self, some_func):
        """
        Suppose it generates the duplicated `sms_token`
        :return:
        """
        some_func.return_value = '123456'
        assert '123456' == rand_six()

Problem:

It does not patch the behavior of random.randint

Question:
How can I put my fake generated list to my randint?

Upvotes: 1

Views: 799

Answers (1)

joe
joe

Reputation: 9494

Thanks to Klaus D. for his comment. I have to stick with module.

  1. Use import random and random.randint(0, 9)
import random

from multy_herr.user_profiles.models import UserProfile


def rand_six():
    """
    Must find the `sms_token` which no `UserProfile`
    :return:
    """
    tmp = ""
    for i in range(6):
        tmp += str(random.randint(0, 9))
    if 0 == UserProfile.objects.filter(sms_token=tmp).count():
        return tmp
    else:
        return rand_six()
  1. Use global in order to get my defined value with given condition. And a bit cheat with my own question. Since I want 2 answers the same, but not last one.
    def _rand111(self, a, b):
        global idx
        if idx in range(12):
            idx += 1
            return 1
        else:
            return 2

    def test_mock_randint(self):
        """
        Test mock the behaviour of `random.randint`
        :return:
        """

        with mock.patch('random.randint', self._rand111):
            assert '111111' == rand_six()
            assert '111111' == rand_six()
            assert '222222' == rand_six()

Upvotes: 2

Related Questions