5

I have a test suite (using nose, not unittest), and I want to patch a function to return a specific sequence of values for every test in the test class. My first attempt, using a simplified example, was:

@patch('time.clock', MagicMock(side_effects=[1, 2]))
class Tests:
    def test_1(self):
        assert time.clock() == 1
        assert time.clock() == 2

    def test_2(self):
        assert time.clock() == 1
        assert time.clock() == 2

However, the MagicMock instance is only created once, so the second test fails when the side effects run out. I can patch each test method separately, but I don't really want to duplicate the patch decorator over all of them (there are a lot more tests than in this example!) The other way I could do it is to create the patch in the setup code like this:

class Tests:
    def setup(self):
        self.old_clock = time.clock
        time.clock = MagicMock(side_effects=[1, 2])

    def teardown(self):
        time.clock = self.old_clock

    def test_1(self):
        assert time.clock() == 1
        assert time.clock() == 2

    def test_2(self):
        assert time.clock() == 1
        assert time.clock() == 2

But saving and restoring the original function definition seems like something that Mock should be able to do automatically. Is there another method of doing this that I'm missing? Or is my last example the best way of doing this?

2 Answers 2

2
a = (x for x in [1,2])

x = lambda : next(a)

x()

Out: 1

x()

Out: 2

Put your answers into a's list. Change X for your desired name.

Sign up to request clarification or add additional context in comments.

4 Comments

I have no idea what you're getting at here. It doesn't seem to relate the the question at all, and looks like a complicated way of writing x = [1, 2].__iter__().next. What are you trying to say?
well. You want a way to creare a mock of a function. You now rhe order of the reponses. No? x = ["Your first Response", "Your Second Respo", "...etc"].__iter__().next Solves the problem.
I know how to create an iterator and mock a function. My question was whether there is an easy way to reset the mock for every test function.
Sorry, I misunderstood your question. Your setup-teardown solution looks good to me. It keeps the 'magic' inside the test. Is easy to understand, Small and easy to remove.
1

You should just apply the patch to every test, instead of applying it to the class:

class Tests:
    @patch('time.clock', MagicMock(side_effects=[1, 2]))
    def test_1(self):
        assert time.clock() == 1
        assert time.clock() == 2

    @patch('time.clock', MagicMock(side_effects=[1, 2]))
    def test_2(self):
        assert time.clock() == 1
        assert time.clock() == 2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.