1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
# Mocking
## Fake objects
Create a fake object with no attributes:
```python
fake = flexmock()
```
Specify attribute/return value pairs:
```python
fake_plane = flexmock(model="MIG-16", condition="used")
```
Specify methods/return value pairs:
```python
fake_plane = flexmock(fly=lambda: "voooosh!", land=lambda: "landed!")
```
You can mix method and non-method attributes by making the return value a lambda
for callable attributes.
Flexmock fake objects support the full range of flexmock commands but differ
from partial mocks (described below) in that
`should_receive()` can assign them new methods rather than being limited to
acting on methods they already possess.
```python
fake_plane = flexmock(fly=lambda: "vooosh!")
fake_plane.should_receive("land").and_return("landed!")
```
## Partial mocks
Flexmock provides three syntactic ways to hook into an existing object and
override its methods.
Mark the object as partially mocked, allowing it to be used to create new
expectations:
```python
flexmock(plane)
plane.should_receive("fly").and_return("vooosh!").once()
plane.should_receive("land").and_return("landed!").once()
```
!!! note
If you do not provide a return value then None is returned by default. Thus,
`and_return()` is equivalent to `and_return(None)` is equivalent to simply
leaving off `and_return`.
Equivalent syntax assigns the partially mocked object to a variable:
```python
plane = flexmock(plane)
plane.should_receive("fly").and_return("vooosh!").once()
plane.should_receive("land").and_return("landed!").once()
```
Or you can combine everything into one line if there is only one method to
override:
```python
flexmock(plane).should_receive("fly").and_return("vooosh!").once()
```
You can also return the mock object after setting the expectations:
```python
plane = flexmock(plane).should_receive("fly").and_return("vooosh!").mock()
```
Note the `mock` modifier above -- the expectation chain returns an Expectation
otherwise:
```python
plane.should_receive("land").with_args().and_return("foo", "bar")
```
!!! note
If you do not provide a `with_args()` modifier then any set of arguments,
including none, will be matched. However, if you specify `with_args()` the
expectation will only match exactly zero arguments.
## Attributes and properties
Just as you are able to stub return values for functions and methods, flexmock
also allows to stub out non-callable attributes and even (getter) properties.
Syntax for this is exactly the same as for methods and functions.
### Shorthand
Instead of writing out the lengthy `should_receive`/`and_return` statements, you
can also use the handy shorthand approach of passing them in as key=value pairs
to the `flexmock()` function. For example, we can stub out two methods of the
plane object in the same call:
```python
flexmock(plane, fly="voooosh!", land=("foo", "bar"))
```
This approach is handy and quick but only limited to stubs, i.e. it is not
possible to further modify these kind of calls with any of the usual modifiers
described below.
## Class level mocks
If the object you partially mock is a class, flexmock effectively replaces the
method for all instances of that class.
```python
class User:
def get_name(self):
return "George Bush"
flexmock(User)
User.should_receive("get_name").and_return("Bill Clinton")
bubba = User()
bubba.get_name() # returns "Bill Clinton"
```
## Raising exceptions
You can make the mocked method raise an exception instead of returning a value:
```python
flexmock(plane).should_receive("fly").and_raise(BadWeatherException)
```
You can also add a message to the exception being raised:
```python
flexmock(plane).should_receive("fly").and_raise(
BadWeatherException, "Oh noes, rain!"
)
```
## Private methods
One of the small pains of writing unit tests is that it can be difficult to get
at the private methods since Python "conveniently" renames them when you try to
access them from outside the object. With flexmock there is nothing special you
need to do to -- mocking private methods is exactly the same as any other
methods.
|