DEV Community

Discussion on: Code Smell 135 - Interfaces With just One Realization

Collapse
 
mcsee profile image
Maxi Contieri

I don't follow your tests example

Can you add a small piece of code as an example?

Collapse
 
davidkroell profile image
David Kröll
public class Car
{
    private readonly IEngine _engine;
    private bool isRunning;

    public Car(IEngine engine)
    {
        _engine = engine;
    }

    public void Start()
    {
        if (!isRunning)
        {
            _engine.Start();
            isRunning = true;
        }
    }
}

public interface IEngine
{
    void Start();
}

public class DieselEngine : IEngine
{
    public void Start()
    {
        Console.WriteLine("Starting diesel engine");
    }
}
Enter fullscreen mode Exit fullscreen mode

Assume you have a class Car which depends on a class DieselEngine. It would not be possible to write a unit test just for the Car when the concrete type DieselEngine is required from the Car constructor. Instead, the test have then to be written keeping in mind that also the concrete implementation for DieselEngine is going to be tested.

When you extract an interface IEngine, you can write a test for the Car itself again (without relying on concrete DieselEngine). Typically you do not have to create another realization of the IEngine interface - instead you can use a mocking framework which does this for you, and check if the method IEngine.Start is only called if the engine is currently off.

I hope this answers your question

Thread Thread
 
mcsee profile image
Maxi Contieri

Thank you very much for the code.

I think the problem is here

"Assume you have a class Car which depends on a class DieselEngine. It would not be possible to write a unit test just for the Car when the concrete type DieselEngine is required from the Car constructor."

Why not test the Car with a DieselEngine ? This is a real business scenario

Also, IMHO , Callling an interface IEngine is another smell. Even dough I know it is a standard practice.
Can I use your code snippet in another smell ?

Thread Thread
 
gorynych profile image
Stepan Mozyra

"Why not test the Car with a DieselEngine ?" - This is idea behind unit tests :) to have a single unit under the test.

If you do unit testing in your project - you will always have two implementations of your interfaces.

"This is a real business scenario" - Testing of business scenarios is just an another kind of tests.

Thread Thread
 
mcsee profile image
Maxi Contieri

Right !

You have two interfaces realizations. Therefore this code smell does not apply anymore

Thread Thread
 
davidkroell profile image
David Kröll

Can I use your code snippet in another smell ?

Yes feel free.

It depends on what you call a unit I think, bit you're right. If the DieselEngine is testable at all (could be a real DieselEngine which is not availabe during CI test run, etc).

Thread Thread
 
mcsee profile image
Maxi Contieri

Build your abstractions with TDD so they will be testaable from their inception