开发者

Design considerations when including unit testing in a .Net application?

All methods in .Net are considered final by default unless the virtual modifier is used. Java is the other way around. All methods are virtual and can be overridden. When it comes to unit testing with frameworks such as Moq, RhinoMock etc we can either create a mock or a stub. If we are to create a mock we need an interface. This forces us to use interfaces everywhere if it is not necessary just to be able to test our code.

On the other hand we can create stubs but then the methods that we are stubbing out need to be virtual so that the framework can override them.

There are other mocking frameworks out there that use AOP, such as TypeMock, but I am not sure I can motiviate spending money on a framework like that when there are such good open source and free ones.

I know that non-virtual and interface methods are both slightly slower. But this shouldn't really impact an application on today's hardware.

So my question is: Should almost everything be an interface, even if it is not really encapsulating some so开发者_开发百科rt of behavior? Or should we make methods virtual as needed to aid our testing. Both feel a little hacky and unnecessary to me.

What are you thoughts?


Personally I find that using interfaces for dependencies improves the design anyway. It makes it clear exactly what you're depending on, rather than just whatever public and internal methods happen to be exposed by the implementation class.

Note that this doesn't mean that every class needs to have an interface... just those you wish to act as dependencies. For example, I wouldn't create interfaces for types which are mostly "simple data", or exceptions. But if a class is acting as a "service" in some respect, an interface feels appropriate. It would be nice if there were an easier way of expressing that interface rather than having a separate file, but conceptually I think it's clean.

(This opinion makes me somewhat old-fashioned, I realize, but it helps me understand my design, at least :)


I tend to divide my solutions into components with a well-defined area of responsibility, such as a set of classes and other types working together to solve some specific problem. Classes that make up the public facade of such a component typically benefit greatly from having interfaces, as it allows me to easily replace or stub them for testing and general maintenance. Whether you add interfaces for the internally used classes just for the purpose of unit testing is a decision usually decided by the internal complexity as well as whether the component itself makes use of other components that need to be stubbed out.

Creating an interface for a class is really rather simple, given that Visual Studio even has the necessary refactoring options built-in (right-click, refactor->extract interface). As such, the coding effort of creating the interface is somewhat trivial (assuming that the design is driven by how the class ends up looking).

Although some effort is involved in maintaining the interfaces over time, I find myself using them more often than not. It reduces the public surface of an API, which makes maintenance easier, and if you have tools like R# then there is almost no additional effort involved.

It's also worth mentioning that TypeMock and Moles (the Pex companion) both hook into the profiling API. As such it is somewhat unlike AOP even though they provide AOP-like capabilities. These are useful when you need to intercept static methods or regular field accesses, something you cannot model with interfaces.


I've generally found that I usually code against an interface for loose coupling between concrete types, inversion of control and dependency injection and to aid testability.

Like you say however, the are times when creating an interface may be noise. In these particular scenarios, you need to weigh up whether

  1. The design is correct
  2. you actually need to be able to mock/stub the type
  3. marking members as virtual will harm the design
  4. will introducing an interface aid the design

(I'd consider both 3 and 4 at the same time)

If you find that you do need to be able to mock/stub the type then with most frameworks you will need to provide some mechanism to be able to do this and virtual members and interfaces are the two obvious choices.

Mocking and stubbing frameworks that don't require an interface or virtual member are Typemock, Moles and I believe JustMock. The first two use the profiling API ( and I believe JustMock does too) which essentially redirect the method call to somewhere else that you have defined. There's some debate about whether being able to do this is a good thing as it may mean you have to think less about the design, however there are certainly times where it can really help (DateTime.Now is the classic example).

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜