8

I am trying to Mock an import in python for a test. My code looks something like this.

"""Python file description."""

import sys
import pytest

import datetime as dt

from unittest.mock import Mock

sys.modules['module_A'] = Mock()

from module_to_test import function_to_test

where I need to mock module_A as a dependency for module_to_test.

On save, VSCode auto-orders this alphabetically, and as a result creates the Mock after it tries to import from the module with the dependency.

How do I prevent the Sort Imports from ordering a subset of files? This could be through a list of files, a glob, regex or similar?

Glob pattern of the test file ./tests/test_*.py.


Update - Partial solution posted below.

Little Bobby Tables
  • 4,466
  • 4
  • 29
  • 46
  • 1
    So what's a higher priority problem here, mocking module or un-sorting imports? Suggested reading: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem, wikipedia: https://en.wikipedia.org/wiki/XY_problem – 0xc0de Apr 09 '19 at 09:39
  • @0xc0de my priority is to get my tests running so that I can deploy my script ASAP. Time taken to add on line to `settings.json` - 2 minutes. Time taken to read, understand and refactor my *tests* - lots of minutes. – Little Bobby Tables Apr 09 '19 at 09:44
  • @0xc0de that isn't to say I won't eventually, or that it isn't the right thing to do as per pep8. – Little Bobby Tables Apr 09 '19 at 09:53
  • Those lots of minutes will help you get your pep8 compliant work done quickly in future too. – 0xc0de Apr 09 '19 at 10:14

5 Answers5

14

If like mine your VSCode config is using isort (not autopep8) to do the import sorting, then you can override it on a selective basis like this:

app = Flask(__name__)
from . import views  # isort:skip

i.e. Add the # isort:skip comment to the import you don't want to jump to the top of the file.

Source: https://github.com/timothycrosley/isort#skip-processing-of-imports-outside-of-configuration

cmuk
  • 473
  • 5
  • 9
  • VSCode+isort here: this doesn't work – HAL9000 Feb 07 '22 at 12:30
  • This also worked to stop isort from adding parenthesis around my comma-separated list of symbols when importing. i.e. it was turning `from a import x, y, z` into `from a import (x, y, z)` which was borking something. `from a import x, y, z # isort:skip` stopped it. – LightCC Mar 11 '22 at 04:43
  • FYI, I'm on Windows 10 using vscode 1.66.1 and use `editor.codeActionsOnSave`. – adam.hendry Apr 09 '22 at 03:15
7

VS Code runs autopep8 at save time and you can add the # noqa or # nopep8 comment at the end of a line to exclude that line from checking/sorting:

sys.modules['module_A'] = Mock()

from module_to_test import function_to_test # noqa
mrts
  • 16,697
  • 8
  • 89
  • 72
3

I don't think you should worry about sorting imports. Mock should take care of it, your tests should use context managers or decorators provided by mock module instead of directly assigning a Mock object yourself.

Take a look at 'patch'.

Also look at 'where to patch'

0xc0de
  • 8,028
  • 5
  • 49
  • 75
  • Thanks for the input. I was going off [this answer](https://stackoverflow.com/a/8658332/4049396), which seems to be a way of mocking that has worked for me until now. This question is more about how to stop the sort from happening. That said, I don't really understand how to apply a patch to pytest so I haven't tried it. – Little Bobby Tables Apr 04 '19 at 09:43
  • 1
    See https://docs.pytest.org/en/latest/reference.html#monkeypatch on how to mock in pytest. – Brett Cannon Apr 08 '19 at 21:42
1

Currently, you can't turn off import sorting an a per-module level through a VS Code-specific setting (it's either on or off). It would need to be supported by isort itself somehow.

Little Bobby Tables
  • 4,466
  • 4
  • 29
  • 46
Brett Cannon
  • 14,438
  • 3
  • 45
  • 40
1

The problem here is coming from the autopep8 rules being run at save time. Specifically, rule E402, which requires all imports first.

Although I could not get VS Code or any of its packages to run a on the subset of files, I did find a solution to exclude a subset of autopep8 rules. Here is what the settings.json entry looks like,

    "python.formatting.provider": "autopep8",
    "python.formatting.autopep8Args": [
        "--ignore",
        "E402"
    ],

See this answer for more information.

Little Bobby Tables
  • 4,466
  • 4
  • 29
  • 46