Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# stubbing. Interface for every testable object?

I've seen multiple answers regarding 'how to stub your classes so you can control what happens within the SUT'.

They say one thing:

Create an interface and inject that interface using dependency injection and create a stub using that same interface that you then inject into the SUT.

However, what I've learned in my previous working places:

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

Does that mean that for every class that has a specific function-layout you have to create an interface?

That would mean the amount of classes/files would just about be twice as many.

As seen in the example below, is this 'the way to go' or am I missing something in my unit testing process?

As a note: I am using VS2012 Express. That means no 'Faker' framework. I am using the 'standard' VS2012 unit testing framework.

As a very, very simple example, which allows me to stub each interface passed down to a 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
    }
}
like image 889
Daan Timmer Avatar asked May 23 '13 23:05

Daan Timmer


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


2 Answers

In my opinion, you should not create interfaces just for the purpose of unit testing. If you start adding code abstractions to please the tools, then they are not helping you to be more productive. The code you write should ideally serve a specific business purpose/need - either directly, or indirectly by making the code base easier to maintain or evolve.

Interfaces sometimes do this, but certainly not always. I find that providing interfaces for components is usually a good thing, but try to avoid using interfaces for internal classes (that is, code only used inside of the given project, regardless of whether the types are declared public or not). This is because a component (as in, a set of classes working together to solve some specific problem) represents a larger concept (such as a logger or a scheduler), which is something that I may feasibly want to replace or stub out when testing.

The solution (hat tip to Robert for being first in the comments) is to use a mocking framework to generate a compatible substitution type at run-time. Mocking frameworks then allow you to verify that the class being tested interacted correctly with the substituted dummy. Moq is as mentioned a snazzy choice. Rhino.Mocks and NMock are two other popular frameworks. Typemock Isolator hooks into the profiler and is among the more powerful options (allows you to substitute even non-virtual private members), but is a commercial tool.

It's no good making up rules for how much you should unit test. It depends on what you're developing and what your goals are - if correctness always trumps time-to-market and cost is not a factor then unit testing everything is great. Most people are not so lucky and will have to compromise to achieve a reasonable level of test coverage. How much you should test may also depend on overall skill level of the team, expected lifetime and reuse of the code being written, etc.

like image 187
Morten Mertner Avatar answered Sep 25 '22 21:09

Morten Mertner


Yes and no. In order to stub dependency you need some sort of abstraction, but that's in majority because of how mocking frameworks work (not all, naturally).

Consider simple example. You test class A that takes dependencies to classes B and C. For unit tests of A to work, you need to mock B and C - you'll need IB and IC (or base classes /w virtual members). Do you need IA? No, at least not for this test. And unless A becomes dependency to some other class, abstracting it behind interface/base class is not required.

Abstraction is great as it helps you build losely coupled code. You should abstract your dependencies. However, in practice some classes need not to be abstracted as they serve top-level/end-of-hierarchy/root roles and are not used elsewhere.

like image 20
k.m Avatar answered Sep 22 '22 21:09

k.m