Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to patch OS.mkdir with Mock?

I am trying to unit test using the Mock module with pytest.

I want os.path.isdir() to return False, and os.mkdir() not to run; I just want to verify the correct arguments are passed to it.

I think you only need to look at set_path method

My app:

import pytumblr, os, sys, prowlpy, json, collections
from urllib2 import urlopen
from time import sleep
from apiclient.discovery import build

class Site(object):
    """A generic site."""
    def __init__(self, user):
        self.user = user

    def set_path(self):
        if os.path.isdir(self.user_dir):            # if user dir already exists
            print "**Directory already exists: ", self.user_dir
        else:
            os.mkdir(self.user_dir)                 # else create user dir
            print "Created Directory: ", self.user_dir

class Tumblr(Site):
    """A tumblr blog."""
    type = "tumblr"
    type_dir = os.path.join(os.getcwd(), type)
    def __init__(self, user):
        super(Tumblr, self).__init__(user)
        self.user_dir = os.path.join(Tumblr.type_dir, self.user)

My test always fails as shown below here:

import tumblrip_new as tum
import mock

    @mock.patch('tumblrip_new.os')
    @mock.patch('tumblrip_new.os.path')
    def test_create_new_user_dir(self, mock_path, mock_os):
        """Creates a directory if one does not exist."""
        t = tum.Tumblr("username")
        # directory does not exist:
        mock_path.isdir.return_value = False
        t.set_path()
        mock_os.mkdir.assert_called_with(t.user_dir)

Output shows the reason for the failure:

_mock_self = <MagicMock name='os.mkdir' id='33647664'>
args = (<MagicMock name='os.path.join()' id='33568048'>,), kwargs = {}
self = <MagicMock name='os.mkdir' id='33647664'>
expected = "mkdir(<MagicMock name='os.path.join()' id='33568048'>)"

>   ???
E   AssertionError: Expected call: mkdir(<MagicMock name='os.path.join()' id='3
568048'>)
E   Not called

build\bdist.win32\egg\mock.py:831: AssertionError
===================== 1 failed, 3 passed in 0.22 seconds ======================
like image 847
BBedit Avatar asked Jul 11 '14 19:07

BBedit


2 Answers

I fixed it in the following way:

@mock.patch('tumblrip_new.os.path')
@mock.patch('tumblrip_new.os')
def test_create_new_user_dir(self, mock_os, mock_path):
    """Creates a directory if one does not exist."""
    t = tum.Tumblr("username")
    # directory does not exist:
    mock_path.isdir.return_value=False
    t.set_path()
    mock_os.mkdir.assert_called_with(t.user_dir)
like image 140
BBedit Avatar answered Oct 28 '22 13:10

BBedit


using side effect to update mock behavior (os.path.isdir):

import os
import unittest
from mock import Mock, MagicMock, patch
from contextlib import nested

"""Creates a directory if one does not exist."""


class Site(object):
    """A generic site."""
    def __init__(self, user):
        self.user = user

    def set_path(self):
        if os.path.isdir(self.user_dir):            # if user dir already exists
            print "**Directory already exists: ", self.user_dir
        else:
            os.mkdir(self.user_dir)                 # else create user dir
            print "Created Directory: ", self.user_dir


class Tumblr(Site):
    """A tumblr blog."""
    type = "tumblr"
    type_dir = os.path.join(os.getcwd(), type)

    def __init__(self, user):
        super(Tumblr, self).__init__(user)
        self.user_dir = os.path.join(Tumblr.type_dir, self.user)


class testCreateDir(unittest.TestCase):

    def test_create_new_user_dir(self):

        os = MagicMock()
        os.path = MagicMock()

        os.path.isdir = Mock(return_value=False)
        os.path.join = Mock(return_value="user_dir")

        mkdir = Mock()

        def update_status(*args):
            mkdir(args[0])
            os.path.isdir.return_value = True

        os.mkdir = Mock(side_effect=update_status)

        with nested(patch('os.path', os.path), patch('os.mkdir', os.mkdir)):
            t = Tumblr("username")
            t.set_path()
            mkdir.assert_called_with(t.user_dir)
            t.set_path()
            t.set_path()
            t.set_path()
            mkdir.assert_called_once_with(t.user_dir)
like image 31
Wajih Avatar answered Oct 28 '22 12:10

Wajih