C # stubbing. Interface for each object being scanned?

I saw several answers regarding "how to drown out your classes so you can control what happens in SUT."

They say one thing:

Create an interface and add this interface using dependency injection, and create a stub using the same interface that you then enter into the SUT.

However, what I learned in my previous jobs:

If you are unit test, you check all classes / functionality.

Does this mean that for each class that has a specific function layout, you need to create an interface?

This would mean that the number of classes / files is about twice as large.

As you can see from the example below, is this a β€œway to go” or am I missing something during unit testing?

As a note: I am using VS2012 Express. This means the lack of a "Faker" frame. I use the standard unit testing system VS2012.

As a very, very simple example that allows me to drown out every interface passed to the SUT.

IFoo.cs

public interface IFoo { string GetName(); } 

Foo.cs

 public class Foo : IFoo { public string GetName() { return "logic goes here"; } } 

IBar.cs:

 public interface IBar : IFoo { IFoo GetFoo(); } 

Bar.cs:

 public class Bar : IBar { public string GetName() { return "logic goes here"; } public IFoo GetFoo() { return null; // some instance of IFoo } } 

IBaz.cs:

 public interface IBaz { IBar GetBar(); } 

Baz.cs:

 public class Baz { public IBar GetBar() { return null; // some instance of IBar } } 
+6
source share
5 answers

Yes and no. In order to fade the dependency, you need some kind of abstraction, but this is in most cases due to the fact that mocking frameworks work (not all, of course).

Consider a simple example. You are testing class A , which accepts dependencies on classes B and C For A unit tests, to work you need to make fun of B and C - you need IB and IC ( or the base classes / w of virtual members ). Do you need an IA ? No, at least not for this test. And if A does not become dependent on any other class, abstracting it behind the interface / base class is not required.

The abstraction is great, as it helps you create code related codes. You must abstract your dependencies. However, in practice, some classes do not need to be abstracted, because they serve the roles of the top level / end of the hierarchy / root and are not used elsewhere.

+4
source

In my opinion, you should not create interfaces only for unit testing. If you start adding code abstractions to please the tools, then they do not help you to be more productive. The code you write should ideally serve specific business goals / needs - directly or indirectly, simplifying the maintenance or development of the code base.

Interfaces sometimes do this, but certainly not always. I believe that providing interfaces for components is usually good, but try to avoid using interfaces for inner classes (that is, code used only within this project, regardless of whether they are publicly declared or not). This is because a component (such as a set of classes working together to solve a particular problem) is a larger concept (such as a logger or scheduler) that I might want to replace or drown during testing.

The solution (a hint to Robert for the first one in the comments) is to use a fake structure to create a compatible substitution type at runtime. Then the replacement frameworks make sure that the tested class interacts correctly with the substituted dummy. Mock, as already mentioned, was a fun choice. Rhino.Mocks and NMock are two other popular frameworks. Typemock Isolator connects to the profiler and is one of the most powerful parameters (it allows you to replace even non-virtual private participants), but it is a commercial tool.

There are no good rules for how much you should unit test. It depends on what you are developing and what your goals are - if the correctness always exceeds the time to market, and the cost is not a factor, and unit testing is all excellent. Most people are not so lucky and have to compromise in order to achieve a reasonable level of test coverage. How much you should check can also depend on the general level of the team’s qualifications, expected life and reuse of written code, etc.

+6
source

Perhaps, from the point of view of a purist, this is the right way, but it is very important to make sure that external dependencies (for example, a database, network access, etc.) are all that are expensive and time-consuming in terms of computing power, and all that is not completely deterministic, abstracts and is easily replaced in your unit tests.

+3
source

From a testing point of view, there is no need to create an interface for each class in your code. You create an interface to hide the specific execution of external dependencies behind an abstraction layer. Therefore, instead of having a class that requires a direct HTTP connection mixed with your logic, you should isolate the code to connect to the class, whether it embeds an interface that is a member of your class, and embed the layout in place in that interface, so you You can test your logic in isolation, without dependency, and the only "unverified" code is the HTTP connection template code, which can be tested using other means.

0
source

I would go along the route of the virtual method. Creating interfaces for each class that you need for testing becomes really burdensome, especially when you need tools like Resharper to "transition to implementation" every time you want to see a method definition. And there is overhead for managing and modifying both files at any time when changing the signature of a method or adding a new property or method.

0
source

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


All Articles