As a “mockist” TDD practitioner, should I mock other methods in the same class as the method under test?

点点圈 提交于 2019-12-01 15:57:14

The technique is called "mock objects", not "mock methods" for a reason. It encourages designs that divide the system into easily composed, collaborating objects and away from procedural code. The aim is to raise the level of abstraction so that you mostly program by composing objects and rarely write low-level control flow statements.

Personally I think that mocking on self is almost always a code smell. It's testing the implementation rather than the behavior.

Edited for updated sample:

I see now. You have problems testing this class because it has design flaws. This class violates the single responsibility principle. It is doing two things. First, it's managing a connection to a database. It's also syncing.

You need a separate class to manage your database connection. This class will be a dependency of the class under test. The database connecting class can be faked when you unit test the class under test.

Formerly:

As a fellow interaction tester, consider refactoring if you have a need to do this. That class is probably doing too much.

Let me put it to you this way: calling a private method does not make an interaction.

This is one of the main points of TDD. When it hurts your design can be improved.

edited for the new example
To me it looks like you're stubbing confirm_or_create_connection, you're only interested in defining the return call and you're mocking sync, here you're interested in testing if it's really called. (I'll have to check if my definition of stubbing or mocking is the same as the fowler article you referenced. It's been some time since i've read it and I've been using rhinomocks in c# that might have it's own defenition of these terms :-) )

I think for what you're testing mocking and stubbing those calls is the right way to go. You don't want to test to fail if one of those functions has an error, there are other tests for that. You just want to test the operation of sync_path.

I agree with Avdi that this is kind of smelly. The tests are ok but your class might be doing too much.

Guessing wildly, it looks like the connection activity might belong in another object which should be delegated to, in which case you can mock that. I usually recommend against mocking one part of an object to test another part. It suggests that there are two concepts bolted together.

Can you take mocking too far? I don't know about too far but it can be done badly such that you are actually testing the mocks instead of the code, or worse so that you have brittle tests.

But as long as you're writing good tests — tests that confirm your expected behavior, tests that are helping you write the code — then mock on!

Here's a good read on it: "Principle: Don't modify the SUT" at http://xunitpatterns.com/Principles%20of%20Test%20Automation.html#Don

Modifying the class you're testing by mocking or stubbing portions of its implementation is a code smell. The refactoring to get away from it is to move the part you're mocking/stubbing to another class. That said its not always a terrible thing. Its a code smell but its not always inappropriate. For languages like C# or Java where you have good refactoring tools its easy to fix this code smell and I normally would (in C#, assuming Java is similar). I do a lot of development in Lua and Javascript though, where things are a little different. Creating and managing lots of classes in those languages are more difficult, so I am more tolerant of modifying the SUT in tests. Its always something I can fix later once the initial test coverage is there. It does require extra care.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!