Don't duplicate logic in Asserts: The most common mistake on unit testing
Tags: csharp, beginners, testing, tutorial
Published: 2021-11-08 14:15:48

_I originally posted this post on [my blog](https://canro91.github.io/2021/10/11/DontRepeatLogicInAssertions/) a couple of weeks ago. It's part of a series I've been publishing, called [Unit Testing 101](https://canro91.github.io/UnitTesting)._

We have covered some [common mistakes when writing unit tets](https://canro91.github.io/2021/03/29/UnitTestingCommonMistakes/). Some of them may seem obvious. But, we all have made this one mistake when we started to write unit tests. This is the most common mistake when writing unit tests and how to fix it.

**Don't repeat the logic under test when verifying the expected result of a test. Instead, use known, hard-coded, pre-calculated values.**

Let's write some tests for [Stringie](https://github.com/canro91/Testing101), a (fictional) library to manipulate strings with  a fluent interface. Stringie has a `Remove()` method to remove substrings from the end of a string.

We can use Stringie `Remove()` method like this,

```csharp
var hello = "Hello, world!";

string removed = hello.Remove("world!").From(The.End);
// "Hello,"
```

## Don't Copy and Paste the tested logic

**When writing unit tests, don't copy the tested logic and paste it into private methods to use them inside assertions.**

If we bring the tested logic to private methods in our tests, we will have code, and bugs, in two places. Duplication is the root of all evil. Even, inside our tests.

Please, don't write assertions like the one in this test.

```csharp
[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual(RemoveFromEnd(str, "world!"), transformed);
    //              👆👆👆
}

private string RemoveFromEnd(string str, string substring)
{
    var index = str.IndexOf(substring);
    return index >= 0 ? str.Remove(index, substring.Length) : str;
}
```

<figure>
<img src="https://source.unsplash.com/iQ13isgmd7M/800x400" alt="building of apartments" />

<figcaption>That's a lot of duplication. Photo by <a href="https://unsplash.com/@danist07?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Danist Soh</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
  </figcaption>
</figure>

## Don't make internals public

Also, by mistake, we expose internals of the tested logic to use them in assertions. We make private methods public and static. Even to test those private methods directly.

From our [Unit Testing 101](https://canro91.github.io/2021/03/15/UnitTesting101/), we learned to write unit tests through public methods. We should test the observable behavior of our tested code. A returned value, a thrown exception or an external invocation made.

Again, don't write assertions like the one in this test.

```csharp
[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual(Stringie.PrivateMethodMadePublicAndStatic(str), transformed);
    //                      👆👆👆
}
```

## Use known values to Assert

**Instead of duplicating the tested logic, by exposing internals or copy-pasting code into assertions, use a known expected value.**

If we end up using the same expected values, we can create constants for them. Like `const string Hello = "Hello";` or `const string HelloAndComma = "Hello,";` for our example.

For our sample test, simply use the expected substring `"Hello,"`. Like this,

```csharp
[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    // Let's use a known value in our assertions
    Assert.AreEqual("Hello,", transformed);
    //              👆👆👆
}
```

Voilà! That's the most common mistake when writing unit tests. It seems silly! But, often we duplicate Math operations and string concatenations and it passes unnoticed. Remember, don't put too much logic in your tests. Tests should be only assignments and method calls.

If you're new to unit testing, read my post on [how to write your first unit tests in C# with MSTest](https://canro91.github.io/2021/03/15/UnitTesting101/) and check the [4 common mistakes when writing your first tests](https://canro91.github.io/2021/03/29/UnitTestingCommonMistakes/). Also, grab your free copy of my eBook [Unit Testing 101](https://canro91.github.io/UnitTesting).

***

_Hey! I'm Cesar, a software engineer and lifelong learner. If you want to upgrade your unit testing skills, check my course: [Mastering C# Unit Testing with Real-world Examples](https://www.udemy.com/course/mastering-csharp-unit-testing-with-real-world-examples/?referralCode=8456B1B78E2EDE923174) on Udemy. Practice with hands-on exercises and learn best practices by refactoring real-world unit tests._

_Happy testing!_