Should I Have One Interface Per Class For Unit Testing?

Should I define an interface for every public behavior class (excluding data classes)?

I’ve spent many hours searching and reading to find a clear answer. If I search “Do you define an interface for every public class”, 90% of the answers say you should not. However, I have yet to find any such comment explain how to do unit testing otherwise.

Some say Moq can mock concrete classes, but only for members that are declared virtual, and since the constructors cannot be marked virtual, there is no way for Moq to prevent code from running in the constructors (AFAIK). I have no interest in marking every member of every class as virtual.

It seems the answers to this question fall into 3 categories:

  • those who test everything
  • those who test only part of the code
  • those who don’t bother with unit testing

I’ve seen all the arguments on both sides already, but I still haven’t seen any other good way of doing extensive unit testing of the code. Why then, are 90% of the people advocating against this?

The way I’m doing it for now is to place the interface at the top of the same file within a #region, so there is no increase in files, I can easily navigate to the implementation, and it doesn’t clutter the code view. If some interface needs to be implemented several times, nothing prevents me from moving it into separate files later.

One of the main reasons for creating such interface is because of limitations of mocking frameworks. Let’s say the next version of .NET allowed mocking frameworks to mock non-virtual methods, should I still create those interfaces?

Taking a simple example, I have class A, B and C. A depends on IB and IC for testing. Even if not needed for mocking, A still needs instances of B and C injected via dependency injection. Using interfaces is optional for dependency injection but I have yet to see good examples recommending to not use interfaces. So in this hypothetical scenario of not being needed for mocking, should I still create those interfaces or not?

And finally, if creating such interfaces is a good approach (which many disagree with), is there any tool that can auto-generate those interfaces at compile-time so I don’t have to copy the method signatures and comments all the time?

UPDATE: 3 years later, I’ll share my experience.

(since people are still finding this thread and finding it useful judging the votes and 5K views)

Learning unit-testing was hard, but I got to appreciate the benefits in these cases:

  • Writing a recurring-billing system where 100x different scenarios can happen. How the heck would you test that manually!??

  • Writing and refactoring a web API client, where the server can change or break things without notice, or introduce unexpected behaviors for some classes

I personally don’t think interfaces are a code-smell, neither is Moq; but got to find that #region is a code smell so I keep one file per class. I do not like to pass concrete classes via Dependency Injection, so except in rare cases, I use interfaces for anything sent via Dependency Injection.

new keyword? It’s fine for deterministic classes, but anything nondeterministic should be injected via Dependency Injection to make the class deterministic. As an example: Time. Do not use DateTime.Now, but instead, create IDateTimeService that returns the time. If creating a billing system, you’ll then be able to test scenarios at specific times in a deterministic fashion.

I also had issues for showing dialogs with the creation of the ViewModel. What if the dialog’s ViewModel requires IDateTimeService to show the time? I solved the problem in HanumanInstitute.MvvmDialogs by adding IDialogService.CreateViewModel method that uses a function injected in its constructor (often set to () => Locator.GetService<T>() or a custom method for tests.

Creating interfaces is actually quite easy, and helps me see what a specific class is really doing for the public and how to use it. When I get to use my carefully-crafted service, I don’t care about its internal implementations. To avoid duplicate comments, /// <inheritdoc /> is your friend!

I create interfaces for most business classes, not for models. As for ViewModels, it’s generally not necessary unless the ViewModel is used by another ViewModel.

Unit test declarations

These are tips I developed that I’ve never seen anywhere so I’m sharing it for those interested. Dependency trees can get complicated in some cases, and you often don’t need to initialize everything for each test. I initialize each object in a lazy way when needed, and don’t need to care about order and dependencies. The objects are available when needed.

  • The main class I’m testing is available as Model (not sure whether it’s the best name but it doesn’t really matter as long as it’s consistent).

  • When creating the test class, I then decide which concrete dependencies I want, and which ones I want to mock.

  • In this case, I have an audio encoder. I decided to split the code in 3 levels: AudioEncoder for the raw encoding API, EncoderService to take a list of files and pass them through AudioEncoder with progress report and everything without caring about UI, and MainViewModel that allows configuring EncoderService (adding files and folders), and displaying the data and settings in a way that is convenient for the UI.

  • Here, I’m using concrete MainViewModel, concrete EncoderService, and mock AudioEncoder. AudioEncoder has separate Integration tests. DialogService is concrete, and contains a DialogManager that is mocked.

  • For easy initialization of Mocks, you cannot use lambda expression on the right-side of ??=, so I created an Init method that makes the problem go away! Poof magic! See MockAppPaths. I also often create methods to set test-specific mock configurations. Note that if you use Moq Linq syntax to declare your mock quickly, it calls SetupAllProperties, which causes CallBase to not work. You generally want to avoid this.

  • FakeFileSystem has a standard implementation in a shared test library. All members are virtual so I can still mock it to override methods as needed.

public MainViewModel Model => _model ??=
    new MainViewModel(Encoder, DialogService, FakeFileSystem, MockAppPath.Object);
private MainViewModel _model;

public IEncoderService Encoder =>
    _encoder ??= new EncoderService(FakeFileSystem, DialogService, MockAudioEncoder.Object, new FakeDispatcher());
private IEncoderService _encoder;

public Mock<IAudioEncoder> MockAudioEncoder => _mockAudioEncoder ??= new Mock<IAudioEncoder>();
private Mock<IAudioEncoder> _mockAudioEncoder;

protected T Init<T>(Func<T> func) => func();

public Mock<IAppPathService> MockAppPath => _mockAppPath ??= Init(() =>
{
    var mock = new Mock<IAppPathService>();
    mock.Setup(x => x.AudioExtensions).Returns(new[] { "mp3" });
    return mock;
});
private Mock<IAppPathService> _mockAppPath;

public Mock<FakeFileSystemService> FakeFileSystem => _mockFileSystem ??= new Mock<FakeFileSystemService>() { CallBase = true };
private Mock<FakeFileSystemService>? _mockFileSystem;

public IDialogService DialogService => _dialogService ??= new DialogService(MockDialogManager.Object);
private IDialogService _dialogService;

public Mock<IDialogManager> MockDialogManager => _mockDialogManager ??= new Mock<IDialogManager>();
private Mock<IDialogManager> _mockDialogManager;

To make things even easier, I got this base class.

/// <summary>
/// Base class for test classes.
/// </summary>
public class TestsBase
{
    protected readonly ITestOutputHelper _output;

    public TestsBase(ITestOutputHelper output) => _output = output;

    /// <summary>
    /// Allows using a lambda expression after ??= operator.
    /// </summary>
    protected T Init<T>(Func<T> func) => func();
}

public class EncoderServiceTests : TestsBase
{
    public EncoderServiceTests(ITestOutputHelper output) : base(output) 
    { }

    // ...
}

With these guidelines, testing is becoming pretty smooth and orderly!

I hope this helps someone.

0

The underlying problem is the need for mocking in unit testing. Mocking is a code smell – it is unavoidable in some cases, but should not be pervasive in your unit tests.

Mocking is necessary for classes which are interfaces to external services, perform input/output, or are non-deterministic (time, random number generation). But you shouldn’t need to mock every single class in your code. Doing this will lead to brittle tests, where every change in an interface will force you to update the corresponding tests mocks, which defeats the purpose of unit testing.

Mocking frameworks like Moq should IMHO only be used in the case of legacy codebases where you need to add tests to existing code which was not designed for testing. It should not be necessary in well-designed code.

To address the concern that a unit test should only test a single class: This is a misunderstanding. A unit test should test a unit of code which can be tested independently. This might be single function or a set of classes depending on how tightly coupled the code is. For example Math.Max() has no dependencies or side effects, so can be tested independently with no need for mocking. But we don’t actually care if Max internally uses some helper classes. This is an implementation detail, as long as the public behavior corresponds to the specified requirements.

Ideally you want as much as your code to work like Max: A well defined interface with no public dependencies or side-effects. This have advantages in two ways:

  • You don’t need any form of mocking to test Max.
  • If some other component depends on Max there is no need to mock it.

(On that token, let me dispel the myth that static methods are bad for testing. As Math.Max() shows, a static method without side-effects is actually the best thing ever for testing. Just avoid static state.)

Of course I/O and side-effects are necessary in any code. But you want to separate this from any complex logic which requires unit-testing.

I have class A, B and C. A depends on IB and IC for testing. Even if
not needed for mocking, A still needs instances of B and C injected
via dependency injection.

The problem with A B C examples is the answer depends on what A, B and C actually is. So lets take some examples:

A is InvoiceGenerator, B is Customer and C is an Order. Easy – you instantiate Customer and Order with data appropriate for the test. No need for mocking.

But if say A is InvoiceGeneratorAndSender and B is SmtpServer then you may temporarily need to mock SmtpServer, but it would be better to separate the invoice generation from the mailing. Invoice generation could then be tested without any need for mocking. The mailing would be a really shallow wrapper over the SmtpServer so wouldn’t need to be unit tested at all. (But should be integration-tested.)

10

Should I define an interface for every public behavior class (excluding data classes)?

Not necessarily.

I’ve spent many hours searching and reading to find a clear answer. If I search “Do you define an interface for every public class”, 90% of the answers say you should not. However, I have yet to find any such comment explain how to do unit testing otherwise.

Short answer: you are allowed to “unit test” concrete dependencies.

Longer answer: separating interface from implementation allows you to decouple the two. Another way of expressing the same idea is that the interface provides a seam that can be used to introduce alternative implementations.

In the language of Parnas, the interface gives us to insulate modules from the decision of how a particular capability should be implemented.

We tend to use substitutes often in our tests, particularly in our developer tests, because predictable behavior depends on being decoupled from shared mutable state, and fast execution requires avoiding slow code.

But if a particular component is already isolated from shared mutable state, and doesn’t include slow code, the argument for not just using it in your test becomes a lot weaker.

If you apply the Dependency Inversion Principle, an interesting thing happens — the definitions of the interfaces move to the modules that are going to use them, rather than living in the modules that provide the implementations.

In other words, we have the possibility of a substitute not because our implementation supports an interface, but because the consumer does.

class Example {
    void fizz (SomeInterface x) {...}
    void buzz (SomeImplementation x) {...}
}

It’s Example, the consumer of the implementation, that gets to decide how flexible its needs really are.

See Dependency Injection Is NOT The Same As The Dependency Inversion Principle for more details.

So if you find yourself writing a test, and wishing that you could more easily replace some concrete implementation with an alternative, that’s a code smell telling you that the interface of your test subject is too tightly coupled to the implementations of the collaborators. So go fix that first….

Also, I saw several people say you should never use the “new” keyword in the code

That’s not quite right. If you are asking the runtime to store data on the heap, then you are going to be invoking new somewhere. What they are suggesting is that you not mix the new operator into your logic; the decision of how we instantiate an instance of an object can be moved to a module of its own (aka, a “factory”).

Should it be moved? Maybe; there are two pressures here — if the instantiation is likely to change during the lifetime of your code, then having a separate module limits the impact of the change. If you are likely to want to replace the implementation as you move from one environment to another (ex: test vs production), then that’s a good reason to have a replaceable module separating that code.

but don’t specify whether that applies for classes like DateTime, TimeSpan or StringBuilder

Right. My answer is that if we have a stable dependency that gets lots of eyeballs to help share the burden of catching bugs, that doesn’t introduce an indirect dependency on mutable state or the imperative shell, and isn’t something that we want to vary from one environment to another, then introducing a bunch of ceremony to isolate our “unit” from this dependency is a waste of time and annoys the pig.

So StringBuilder goes into the same bucket as String goes into the same bucket as array, as in “of course you can just use it”. If we later need to replace String with a Rope in some contexts — fine, I’ll pay off to that.

Should I use Dependency Injection between those classes?

Horses for Courses — in some cases, it can make sense to pass in your dependencies as replaceble arguments even when the expected implementation is isolated. I’m not going to reject a pull request just because you didn’t make the decision I would have given my limited understanding of the problem that you were investigating — but I might ask you to include a note explaining the motivation for your choice.

3

Should I define an interface for every public behavior class (excluding data classes)?

You should stop thinking this way.

Do not decide you have a Foo and then decide you need an IFoo interface.

Stop thinking about what Foo is and think about what uses Foo, how it uses it and how it doesn’t.

Interfaces, abstract classes, compositional delegators, and any other form of abstraction should not be designed around what something is. That should be designed around how something is used.

Most importantly, whatever is doing the using shouldn’t know which form the abstraction takes. It shouldn’t know if Foo is a keyword interface, abstract class, or delegating to composition.

That not knowing frees you to do it however you like. It lets you change your mind. It keeps you from breaking everything. It makes your question a pointless one because if you do this the answer to your question doesn’t matter.

This is true if you always unit test, sometimes unit test, or never unit test. This isn’t about unit testing. This is about protecting things from knowing more than they need to. Do this and you’ll stop feeling like you have to establish some interface convention.

6

Part of the reason why people argue against it is as a cost/benefit analysis. If you are working in a well-established code base, it may be that you have high confidence that your system works (it has been used by customers for 5 years) but poor unit test coverage. In this case you need to weigh up the time taken to not only to create the unit tests but to refactor the code to be easily unit testable, versus the benefits of doing so. In an established code base such as this one of the main reasons for unit tests is for regression testing and to aid in refactoring. If you find you have to refactor a working but poorly tested code base to do this, you might be creating a headache for yourself.

Again, this depends on a very great many factors. Frequently changed code requires far more extensive regression tests than code that you know from experience has been untouched for ten years.

In a green field, brand new, professional project I’d always very highly recommend extensively unit testing everything. But as legacy systems are usually maintained to help a company turn a profit, you need to consider carefully if adding unit tests will help or hinder you to achieve that goal.

2

This needs a two-fold answer:

  • It is a good idea to decouple your code as it will help you while
    developing and while testing

  • Having interfaces that copy the implementation is a smell since you are not design the real abstraction that lies behind that). Having Car and ICar is a smell since it does not give you any explanation of your business: you might have the interface Car and implementation like Turism, SUV, PickupTruck… (Sometimes, this is also done with inheritance as another way of abstraction)

is there any tool that can auto-generate those interfaces at compile-time so I don’t have to copy the method signatures and comments all the time?

Yes, with a SourceGenerator you can automatically create interfaces.
E.G. https://github.com/daver32/InterfaceGenerator.
You just have to set the [GenerateAutoInterface] attribute to your class and an interface for it will be generated automatically.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật