Hi Ethan,
You have the right idea with mocking the decorator. In order for it to work, you could use monkeypatch to override the decorator with its mock and use importlib.reload to ensure that the changes are reflected (module caching appears to be the reason for which your mock isn't applying as expected.
E.g
You have a function that substracts 2 from a provided value, and a decorator defined in `mydecorator.py` that adds 4 to the value:
```python
from mydecorator import add_four_decorator
@add_four_decorator
def subtract(a):
return a - 2
```
Mocking `add_four_decorator` in the unit test would look like the following:
```python
import calculator
def do_nothing(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def test_calculator_subtract(monkeypatch):
monkeypatch.setattr('mydecorator.add_four_decorator', do_nothing)
import importlib
importlib.reload(calculator)
res = calculator.subtract(12)
assert res == 10
```
Above we are grabbing the monkeypatch fixture and using `monkeypatch.setattr` to pass in the <file_path>.<function_name> of the decorator, and the decorator to replace it with as the second parameter. We are then using importlib.relead to import the module again (rather than using the cached file) to ensure the mock is applied.
The same idea would apply with ajax here and your test_func_to_be_tested would contain something like this:
```python
from q2_sdk.core import web
async def test_func_to_be_tested(mock_success_class):
...
monkeypatch.setattr('q2_sdk.core.web.ajax', mock_decorator)
import importlib
importlib.reload(web)
actual = await handler.func_to_be_tested()
assert isinstance(actual, type(mock_success))
```
Hi Ethan,
You have the right idea with mocking the decorator. In order for it to work, you could use monkeypatch to override the decorator with its mock and use importlib.reload to ensure that the changes are reflected (module caching appears to be the reason for which your mock isn't applying as expected.
E.g
You have a function that substracts 2 from a provided value, and a decorator defined in `mydecorator.py` that adds 4 to the value:
```python
from mydecorator import add_four_decorator
@add_four_decorator
def subtract(a):
return a - 2
```
Mocking `add_four_decorator` in the unit test would look like the following:
```python
from calculator
def do_nothing(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def test_calculator_subtract(monkeypatch):
monkeypatch.setattr('mydecorator.add_four_decorator', do_nothing)
import importlib
importlib.reload(calculator)
res = calculator.subtract(12)
assert res == 10
```
Above we are grabbing the monkeypatch fixture and using `monkeypatch.setattr` to pass in the <file_path>.<function_name> of the decorator, and the decorator to replace it with as the second parameter. We are then using importlib.relead to import the module again (rather than using the cached file) to ensure the mock is applied.
The same idea would apply with ajax here and your test_func_to_be_tested would contain something like this:
```python
from q2_sdk.core import web
async def test_func_to_be_tested(mock_success_class):
...
monkeypatch.setattr('q2_sdk.core.web.ajax', mock_decorator)
import importlib
importlib.reload(web)
actual = await handler.func_to_be_tested()
assert isinstance(actual, type(mock_success))
```
Hi Ethan,
You have the right idea with mocking the decorator. In order for it to work, you could use monkeypatch to override the decorator with its mock and use importlib.reload to ensure that the changes are reflected (module caching appears to be the reason for which your mock isn't applying as expected.
E.g
You have a function that substracts 2 from a provided value, and a decorator defined in `mydecorator.py` that adds 4 to the value:
```python
from mydecorator import add_four_decorator
@add_four_decorator
def subtract(a):
return a - 2
```
Mocking `add_four_decorator` in the unit test would look like the following:
```python
from calculator
def do_nothing(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def test_calculator_subtract(monkeypatch):
monkeypatch.setattr('mydecorator.add_four_decorator', do_nothing)
import importlib
importlib.reload(calculator)
res = calculator.subtract(12)
assert res == 10
```
Above we are grabbing the monkeypatch fixture and using `monkeypatch.setattr` to pass in the <file_path>.<function_name> of the decorator, and the decorator to replace it with as the second parameter. We are then using importlib.relead to import the module again (rather than using the cached file) to ensure the mock is applied.
The same idea would apply with ajax here and your test_func_to_be_tested would contain something like this:
```python
from q2_sdk.core import web
async def test_func_to_be_tested(mock_success_class):
...
monkeypatch.setattr('q2_sdk.core.web.ajax', mock_decorator)
import importlib
importlib.reload(web)
actual = await handler.func_to_be_tested()
assert isinstance(actual, type(mock_success))
```
Hi Ethan,
You have the right idea with mocking the decorator. In order for it to work, you could use monkeypatch to override the decorator with its mock and use importlib.reload to ensure that the changes are reflected (module caching appears to be the reason for which your mock isn't applying as expected.
E.g
You have a function that substracts 2 from a provided value, and a decorator defined in `mydecorator.py` that adds 4 to the value:
```python
from mydecorator import add_four_decorator
@add_four_decorator
def subtract(a):
return a - 2
```
Mocking `add_four_decorator` in the unit test would look like the following:
```python
from calculator import substract
def do_nothing(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def test_calculator_subtract(monkeypatch):
monkeypatch.setattr('mydecorator.add_four_decorator', do_nothing)
import importlib
importlib.reload(calculator)
res = calculator.subtract(12)
assert res == 10
```
Above we are grabbing the monkeypatch fixture and using `monkeypatch.setattr` to pass in the <file_path>.<function_name> of the decorator, and the decorator to replace it with as the second parameter. We are then using importlib.relead to import the module again (rather than using the cached file) to ensure the mock is applied.
The same idea would apply with ajax here and your test_func_to_be_tested would contain something like this:
```python
async def test_func_to_be_tested(mock_success_class):
...
monkeypatch.setattr('q2_sdk.core.web.ajax', mock_decorator)
import importlib
importlib.reload(calculator)
actual = await handler.func_to_be_tested()
assert isinstance(actual, type(mock_success))
```
How can unit tests be written so that the "ajax" decorator does not interfere with testing?
Hi Ethan,
You have the right idea with mocking the decorator. In order for it to work, you could use monkeypatch to override the decorator with its mock and use importlib.reload to ensure that the changes are reflected (module caching appears to be the reason for which your mock isn't applying as expected.
E.g
You have a function that substracts 2 from a provided value, and a decorator defined in `mydecorator.py` that adds 4 to the value:
```python
from mydecorator import add_four_decorator
@add_four_decorator
def subtract(a):
return a - 2
```
Mocking `add_four_decorator` in the unit test would look like the following:
```python
from calculator import substract
def do_nothing(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def test_calculator_subtract(monkeypatch):
monkeypatch.setattr('mydecorator.add_four_decorator', do_nothing)
import importlib
importlib.reload(calculator)
res = calculator.subtract(12)
assert res == 10
```
Above we are grabbing the monkeypatch fixture and using `monkeypatch.setattr` to pass in the <file_path>.<function_name> of the decorator, and the decorator to replace it with as the second parameter. We are then using importlib.relead to import the module again (rather than using the cached file) to ensure the mock is applied.
The same idea would apply with ajax here and your test_func_to_be_tested would contain something like this:
```python
async def test_func_to_be_tested(mock_success_class):
...
monkeypatch.setattr('q2_sdk.core.web.ajax', mock_decorator)
import importlib
importlib.reload(calculator)
actual = await handler.func_to_be_tested()
assert isinstance(actual, type(mock_success))
```