Lesson 2

In our last lesson, we learned the basics of setting up an svnmock session and how basic assertions work. In this, the second part of the tutorial, we'll go over more complex assertions, including making sure functionX is getting called with the return value from methodY.

The Round Peg in the Round Hole

Last time, we learned how to specify the return value from a given function. While that alone would have its uses, it becomes far more powerful when combined with argument assertions.

To take a real-world example, let's say you wanted to test the following code:

from svn import core, repos

core.apr_initialize()
pool = core.svn_pool_create(None)

repo = repos.svn_repos_open("/foo/bar/baz", pool)
repo_fs = repos.svn_repos_fs(repo)

Writing assertions for the first two calls is easy:

from svnmock import mock
from svn import core, repos

mock.add_command(core.apr_initialize)
mock.add_command(core.svn_pool_create, (None,))

But wait; how do you assert that svn_repos_open() should be called with pool, the return value from core.svn_pool_create(None)? It's easier than you think. The full example:

from svnmock import mock
from svn import core, repos

mock.add_command(core.apr_initialize)
pool = mock.add_command(core.svn_pool_create, (None,))

repo = mock.add_command(repos.svn_repos.open, \
	("/foo/bar/baz", pool))
mock.add_command(repos.svn_repos_fs, (repo,))

We capture the return values from the add_command() calls, then feed them to later calls. This is designed to mimic the flow of objects in real code.

If you've been following along at home, typing these examples into your interpreter, you've already gotten a peak at how this works. For example, here's what the second code chunk from this lesson really looks like if typed into Python:

>>> from svnmock import mock
>>> from svn import core, repos
>>>
>>> mock.add_command(core.apr_initialize)
Return<func=<function apr_initialize at 0xb78f7e64)>, \
	args=()>
>>> mock.add_command(core.svn_pool_create, (None,))
Return<func=<function svn_pool_create at 0xb78fd33c)>, \
	args=(None,))>

Recall from lesson 1 that, if you don't explicitly specify a return value, svnmock will "make one up"? Well, this "Return<..." business is a glimpse at that process. If you don't tell add_command() what to return, it will return an instance of a special Return() class; instances of this class record the function that they were returned from, as well as the arguments to that particular function call.

For more information that you could possibly want to know about Return(), see its section in the internals reference manual.

Next...

Next up, we'll discuss simulating error conditions that would be difficult or impossible without svnmock. Failure is your new best friend, in lesson 3!

svnmock