开发者

Is it acceptable to use a 'real' utility class instead of mocking in TDD?

I have a project I am trying to learn unit testing and TDD practices with. I'm finding that I'm getting to quite confusing cases where I am spending a long time setting up mocks for a utility class that's used practically everywhere.

From what I've read about unit testing, if I am testing MyClass, I should be mocking any other functionality (such as provided by UtilityClass). Is it acceptable (assuming that UtilityClass itself has a comprehensive set of tests) to just use the UtilityClass rather than setting up mocks for all the different test cases?

Edit: One of the things I am making a lot of setup for. I am modelling a map, with different objects in different locations. One of the common methods on my utility class is GetDistanceBetween. I am testing methods that have effects on things depending on their individual properties, so for example a test that selects all objects within 5 units of a point and an age over 3 will need several tests (gets old objects in range, ignores old objects out of ra开发者_开发技巧nge, ignores young objects in range, works correctly with multiples of each case) and all of those tests need setup of the GetDistanceBetween method. Multiply that out by every method that uses GetDistanceBetween (almost every one) and the different results that the method should return in different circumstances, and it gets to be a lot of setup.

I can see as I develop this further, there may be more utility class calls, large numbers of objects and a lot of setup on those mock utility classes.


The rule is not "mock everything" but "make tests simple". Mocking should be used if

  1. You can't create an instance with reasonable effort (read: you need a single method call but to create the instance, you need a working database, a DB connection, and five other classes).
  2. Creation of the additional classes is expensive.
  3. The additional classes return unstable values (like the current time or primary keys from a database)


TDD isn't really about testing. Its main benefit is to help you design clean, easy-to-use code that other people can understand and change. If its main benefit was to test then you would be able to write tests after your code, rather than before, with much of the same effect.

If you can, I recommend you stop thinking of them as "unit tests". Instead, think of your tests as examples of how you can use your code, together with descriptions of its behaviour which show why your code is valuable.

As part of that behaviour, your class may want to use some collaborating classes. You can mock these out.

If your utility classes are a core part of your class's behaviour, and your class has no value or its behaviour makes no sense without them, then don't mock them out.

Aaron Digulla's answer is pretty good; I'd rephrase each of his answers according to these principles as:

  1. The behaviour of the collaborating class is complex and independent of the behaviour of the class you're interested in.

  2. Creation of the collaborating class is not a valuable aspect of your class and does not need to be part of your class's responsibility.

  3. The collaborating class provides context which changes the behaviour of your class, and therefore plays into the examples of how you can use it and what kind of behaviour you might expect.

Hope that makes sense! If you liked it, take a look at BDD which uses this kind of vocabulary far more than "test".


In theory you should try to mock all dependencies, but in reality it's never possible. E.g. you are not going to mock the basic classes from the standard library. In your case if the utility class just contains some basic helper methods I think I wouldn't bother to mock it.

If it's more complicated than that or connects to some external resources, you have to mock it. You could consider creating a dedicated mock builder class, that would create you a standard mock (with some standard stubs defined etc), so that you can avoid mocking code duplication in all test classes.


No, it is not acceptable because you are no longer testing the class in isolation which is one of the most important aspects of a unit test. You are testing it with its dependency to this utility even if the utility has its own set of tests. To simplify the creation of mock objects you could use a mock framework. Here are some popular choices:

  • Rhino Mocks
  • Moq
  • NSubstitute

Of course if this utility class is private and can only be used within the scope of the class under test then you don't need to mock it.


Yes, it is acceptable. What's important is to have the UtilityClass thoroughly unit tested and to be able to differentiate if a test is failing because of the Class under test or because of the UtilityClass.

Testing a class in isolation means testing it in a controlled environment, in an environment where one control how the objects behave.
Having to create too many objects in a test setup is a sign that the environment is getting too large and thus is not controlled enough. Time has come to revert to mock objects.


All the previous answers are very good and really match with my point of view about static utility classes and mocking. You have two types of utilities classes, your own classes you write and the third party utility classes.

As the purpose of an utility class is to provide small set of helper methods, your utility classes or a third party utility classes should be very well tested.

First Case: the first condition to use your own utility class (even if static) without mocking, is to provide a set of valid unit tests for this class.

Second Case: if you use a third party utility library, you should have enough confidence to this library. Most of the time, those libraries are well tested and well maintained. You can use it without mocking its methods.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜