简体   繁体   中英

How to check if mock functions has been called?

I'm writing unit tests for a simple function that writes bytes into s3:

import s3fs

def write_bytes_as_csv_to_s3(payload, bucket, key):
    fs = s3fs.S3FileSystem()
    fname = f"{bucket}/{key}"
    print(f"writing {len(payload)} bytes to {fname}")
    with fs.open(fname, "wb") as f:
        f.write(payload)
    return fname


def test_write_bytes_as_csv_to_s3(mocker):
    s3fs_mock = mocker.patch('s3fs.S3FileSystem')
    open_mock = mocker.MagicMock()
    # write_mock = mocker.MagicMock()
    # open_mock.write.return_value = write_mock
    s3fs_mock.open.invoke.return_value = open_mock
    result = write_bytes_as_csv_to_s3('awesome'.encode(), 'random', 'key')
    assert result == 'random/key'
    s3fs_mock.assert_called_once()
    open_mock.assert_called_once()
    # write_mock.assert_called_once()

How can I check if method open and write has been called once? Not sure how to set mocker to cover my case.

The unit-test you written above is perfect and mostly covered all the functionality of the methods which you want to test.

In pytest, there is a functionality to get the unittest coverage report which will show the lines covered by unittest.

Kindly install the pytest plugin html-report(if not installed) and execute the following document:-

py.test --cov=<filename to cover: unittest> --cov-report=html <testfile>

After that, you would likely found a html file in the current location o/r in the htmlconv / directory. And from that, you could easily figure it out about the line covered and also the percentage of the unittest test coverage.

The issue is understanding how each mock is created and what exactly it mocks. For example mocker.patch('s3fs.S3FileSystem') returns a mock of s3fs.S3FileSystem , not the instance returned by calling s3fs.S3FileSystem() . Then to mock with fs.open(fname, "wb") as f you need to mock what the __enter__ dunder method returns. Hopefully the following code makes the relations clear:

def test_write_bytes_as_csv_to_s3(mocker):
    # Mock of the open's context manager
    open_cm_mock = mocker.MagicMock()

    # Mock of the object returned by fs.open()
    open_mock = mocker.MagicMock()
    open_mock.__enter__.return_value = open_cm_mock

    # Mock of the new instance returned by s3fs.S3FileSystem()
    fs_mock = mocker.MagicMock()
    fs_mock.open.return_value = open_mock

    # Patching of s3fs.S3FileSystem 
    mocker.patch('s3fs.S3FileSystem').return_value = fs_mock

    # Running the tested code and making assertions
    result = write_bytes_as_csv_to_s3('awesome'.encode(), 'random', 'key')

    assert result == 'random/key'
    assert open_cm_mock.write.call_count == 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM