<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis" -->

---
title: 4 ways to create Unit Tests without Interfaces in C#
description: C# developers often create an interface for every class just to enable mocking in unit tests. This piece argues that's unnecessary and walks through four...
canonical: https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: 4 ways to create Unit Tests without Interfaces in C# | daily.dev
og:description: C# developers often create an interface for every class just to enable mocking in unit tests. This piece argues that's unnecessary and walks through four...
og:url: https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis
og:image: https://api.daily.dev/og/posts/wIxDHLZiS.png
og:image:alt: 4 ways to create Unit Tests without Interfaces in C#
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 4 ways to create Unit Tests without Interfaces in C#

**[Code4IT](https://daily.dev/sources/code4it)** · 14 min read · 0 upvotes · 0 comments

## Summary

C# developers often create an interface for every class just to enable mocking in unit tests. This piece argues that's unnecessary and walks through four alternative techniques: using the virtual keyword on a dependency's methods to create stub subclasses, using virtual on the consuming service itself to stub out dependency calls, using the new keyword to hide base implementations without virtual, and marking a method virtual so Moq can mock a concrete class directly. Each approach is demonstrated with before/after C# code and working NUnit test examples, along with trade-offs like needing protected parameterless constructors when null-checks exist. The piece closes by acknowledging interfaces still have non-technical benefits (discoverability, TDD workflow) and that removing them is a matter of taste.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.code4it.dev/blog/unit-tests-without-interfaces>

## Questions this post answers

### How do I mock a concrete C# class with Moq instead of creating an interface just for testing?

Mark the method you need to control as virtual on the concrete class, then Moq can override it. Without virtual, Moq throws 'System.NotSupportedException: Unsupported expression... Non-overridable members may not be used in setup / verification expressions.' Once the method is virtual, Mock<NumbersRepository>() and .Setup(_ => _.GetNumbers()) work normally.

_daily.dev surfaces more patterns like this for developers rethinking interface-heavy mocking habits._

### How can I create a stub for a class that has a protected dependency without an interface, when the constructor throws on null?

Add a protected parameterless constructor alongside the normal constructor's ArgumentNullException.ThrowIfNull check. A test-only subclass can then call the protected constructor via base(), bypassing the null check, while marking the methods it needs to control as virtual to override them with stub values.

_developers wiring up stub-based tests can find more C# testing techniques via daily.dev._

### What's the difference between using the new keyword and virtual keyword to override a method in a C# subclass for testing purposes?

Using new to hide a base method avoids having to clutter every class in the codebase with the virtual keyword, since the base method stays non-virtual while the subclass defines its own version with 'new'. Functionally both let a stub subclass redefine behavior, but the practical trade-offs between the two approaches for testing remain an open question the author poses to readers.

_daily.dev helps C# developers compare approaches like this when deciding how to structure testable code._

## Similar posts on daily.dev

- [5 Architecture Tests You Should Add to Your .NET Projects](https://daily.dev/posts/5-architecture-tests-you-should-add-to-your-net-projects-srtuu4tjc) · Milan Jovanović · 20 upvotes · 0 comments
- [Stop Writing Database-Dependent Tests — Mock Your Data Access Layer](https://daily.dev/posts/stop-writing-database-dependent-tests-mock-your-data-access-layer-quo7rycbz) · Javarevisited · 98 upvotes · 10 comments
- [Testing the untestable](https://daily.dev/posts/testing-the-untestable-lw2nlebp0) · A Java geek · 0 upvotes · 0 comments
- [To test, or not to Test? Part 2 – Make it hard to make mistakes](https://daily.dev/posts/to-test-or-not-to-test-part-2-make-it-hard-to-make-mistakes-fnfxbqcof) · We Are .NET · 0 upvotes · 0 comments

---

Tags: [#testing](https://daily.dev/tags/testing), [#.net](https://daily.dev/tags/.net), [#c#](https://daily.dev/tags/c#), [#dependency-injection](https://daily.dev/tags/dependency-injection)

[View this post on daily.dev](https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"4 ways to create Unit Tests without Interfaces in C#","url":"https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis"},"datePublished":"2026-10-04T13:06:30.274Z","dateModified":"2026-10-04T13:19:20.179Z","description":"C# developers often create an interface for every class just to enable mocking in unit tests. This piece argues that's unnecessary and walks through four...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/8f41ee9fc159c0876092b74009caa533?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/8f41ee9fc159c0876092b74009caa533?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Code4IT","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Code4IT","logo":"https://media.daily.dev/image/upload/s--OaaG4G10--/f_auto,q_auto/v1791119049/logos/code4it?_a=BAMAMicg0","url":"https://daily.dev/sources/code4it"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"testing,.net,c#,dependency-injection","timeRequired":"PT14M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Code4IT","item":"https://daily.dev/sources/code4it"},{"@type":"ListItem","position":3,"name":"4 ways to create Unit Tests without Interfaces in C#"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/4-ways-to-create-unit-tests-without-interfaces-in-c--wixdhlzis#faq","mainEntity":[{"@type":"Question","name":"How do I mock a concrete C# class with Moq instead of creating an interface just for testing?","acceptedAnswer":{"@type":"Answer","text":"Mark the method you need to control as virtual on the concrete class, then Moq can override it. Without virtual, Moq throws 'System.NotSupportedException: Unsupported expression... Non-overridable members may not be used in setup / verification expressions.' Once the method is virtual, Mock<NumbersRepository>() and .Setup(_ => _.GetNumbers()) work normally. daily.dev surfaces more patterns like this for developers rethinking interface-heavy mocking habits."}},{"@type":"Question","name":"How can I create a stub for a class that has a protected dependency without an interface, when the constructor throws on null?","acceptedAnswer":{"@type":"Answer","text":"Add a protected parameterless constructor alongside the normal constructor's ArgumentNullException.ThrowIfNull check. A test-only subclass can then call the protected constructor via base(), bypassing the null check, while marking the methods it needs to control as virtual to override them with stub values. developers wiring up stub-based tests can find more C# testing techniques via daily.dev."}},{"@type":"Question","name":"What's the difference between using the new keyword and virtual keyword to override a method in a C# subclass for testing purposes?","acceptedAnswer":{"@type":"Answer","text":"Using new to hide a base method avoids having to clutter every class in the codebase with the virtual keyword, since the base method stays non-virtual while the subclass defines its own version with 'new'. Functionally both let a stub subclass redefine behavior, but the practical trade-offs between the two approaches for testing remain an open question the author poses to readers. daily.dev helps C# developers compare approaches like this when deciding how to structure testable code."}}]}
```

