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

All methods in .Net are considered final by default unless a 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 frames such as Moq, RhinoMock, etc., we can either create a layout or a stub. If we want to create a layout, we need an interface. This forces us to use interfaces everywhere, if there is no need to just check our code.

On the other hand, we can create stubs, but then the methods we execute must be virtual so that the infrastructure can override them.

There are other mocking frameworks in which AOP is used, for example TypeMock, but I'm not sure that I can stimulate spending money on such a framework when there are such good open and free versions.

I know that non-virtual and front-end methods are a bit slower. But this should not affect the application on today's hardware.

So my question is: should almost everything be an interface, even if it does not encapsulate some kind of behavior? Or we should create virtual methods necessary for our testing. Both feel a bit hacked and unnecessary for me.

What do you think?

+4
source share
3 answers

Personally, I think that using interfaces for dependencies improves the design anyway. It clearly states what you depend on, and not just that public and internal methods can be detected by the implementation class.

Note that this does not mean that every class should have an interface ... only the ones you want to execute as dependencies. For example, I would not create interfaces for types that are mostly “simple data” or exceptions. But if the class acts as a “service” in some ways, the interface seems appropriate. It would be nice if there was an easier way to express this interface and not have a separate file, but conceptually I consider it clean.

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

+3
source

I try to divide my decisions into components with a clearly defined area of ​​responsibility, such as a set of classes and other types working together to solve a particular problem. The classes that make up the public façade of such a component tend to benefit greatly from the availability of interfaces, as this allows me to easily replace or drown them for testing and general maintenance. Whether you are adding interfaces for internally used classes for unit testing purposes only, this decision is usually determined by internal complexity, and whether the component itself uses other components that need to be cut through.

Creating an interface for a class is actually quite simple, given that Visual Studio even has the necessary refactoring options built-in (right-click interface, refactor-> extract). Thus, the effort to create code to create the interface is somewhat trivial (assuming that the design is determined by how the class ends).

Despite the fact that over time, some efforts are associated with supporting interfaces, I most often use them. This reduces the open surface of the API, which simplifies maintenance, and if you have tools like R #, there is almost no extra effort.

It is also worth mentioning that TypeMock and Moles (Pex companion) connect to the profiling API. Thus, it is somewhat unlike AOP, although they provide AOP-like capabilities. They are useful when you need to intercept static methods or regular field calls, which you cannot model using interfaces.

+2
source

As a rule, I found that I usually program against an interface for freely connecting between specific types, inverting control and injecting dependencies, and to allow verification.

As you say, however, there are times when creating an interface can be noise. In these specific scenarios you need to weigh

  • Design is right
  • you really need to be able to make fun of / muffle the type
  • Marking members as virtual harms design.
  • will introduce an interface that helps design

(I would consider 3 and 4 at the same time)

If you find that you need to wet / drown 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 two obvious options.

Interchangeable and gating environments that do not require an interface or virtual member, Typemock , Moles , and I believe JustMock . The first two use profiling APIs (and I believe JustMock does too), which essentially redirect the method call to another location that you defined. There is some debate about whether this can be done, this is good, as it may mean that you need to think less about design, but there are certain points where it can really help ( DateTime.Now is a classic example).

0
source

Source: https://habr.com/ru/post/1342255/


All Articles