192 lines
5.2 KiB
Plaintext
192 lines
5.2 KiB
Plaintext
== Why is this an issue?
|
|
|
|
The rule targets test methods that lack an assertion and consist solely of an action and, optionally, a setup.
|
|
|
|
[source,csharp]
|
|
----
|
|
[TestMethod]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
}
|
|
----
|
|
|
|
Such tests only verify that the system under test does not throw any exceptions without providing any guarantees regarding the code's behavior under test.
|
|
Those tests increase the coverage without enforcing anything on the covered code, resulting in a false sense of security.
|
|
|
|
The rule identifies a potential issue when no assertions are present in tests utilizing the following frameworks:
|
|
|
|
* `MSTest`
|
|
* `NUnit`
|
|
* `xUnit`
|
|
* `FluentAssertions` (4.x and 5.x)
|
|
* `NFluent`
|
|
* `NSubstitute`
|
|
* `Moq`
|
|
* `Shoudly`
|
|
|
|
By enforcing the presence of assertions, this rule aims to enhance the reliability and comprehensiveness of tests by ensuring that they provide meaningful validation of the expected behavior.
|
|
|
|
=== Exceptions
|
|
|
|
Test methods that include a call to a custom assertion method will not raise any issues.
|
|
|
|
// This is on purpose not spelled "How to fix it" because:
|
|
// - we cannot mix the generic section with framework-specific sections
|
|
// - we cannot use a subsection with that name.
|
|
=== How can you fix it?
|
|
|
|
To address this issue, you should include assertions to validate the expected behavior.
|
|
Choose an appropriate assertion method provided by your testing framework (such as MSTest, NUnit, xUnit) or select a suitable assertion library like FluentAssertions, NFluent, NSubstitute, Moq, or Shouldly.
|
|
|
|
In addition to using built-in assertion methods, you also have the option to create custom assertion methods. To do this, declare an attribute named `[AssertionMethodAttribute]` and apply it to the respective method. This allows you to encapsulate specific validation logic within your custom assertion methods without raising the issue.
|
|
Here's an example:
|
|
|
|
[source,csharp]
|
|
----
|
|
using System;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
[TestClass]
|
|
public class CustomTestExample
|
|
{
|
|
[TestMethod]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
Validator.AssertCustomEquality(0, actual); // Compliant
|
|
}
|
|
}
|
|
|
|
public static class Validator
|
|
{
|
|
[AssertionMethod]
|
|
public static void AssertCustomEquality(int expected, int actual)
|
|
{
|
|
// ...
|
|
}
|
|
}
|
|
|
|
public class AssertionMethodAttribute : Attribute { }
|
|
----
|
|
|
|
== How to fix it in MSTest
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
[TestMethod]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,csharp,diff-id=1,diff-type=compliant]
|
|
----
|
|
[TestMethod]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
Assert.AreEqual(0, actual);
|
|
}
|
|
----
|
|
|
|
== How to fix it in NUnit
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,csharp,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
[Test]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,csharp,diff-id=2,diff-type=compliant]
|
|
----
|
|
[Test]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
Assert.That(0, Is.EqualTo(actual));
|
|
}
|
|
----
|
|
|
|
== How to fix it in xUnit
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,csharp,diff-id=3,diff-type=noncompliant]
|
|
----
|
|
[Fact]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,csharp,diff-id=3,diff-type=compliant]
|
|
----
|
|
[Fact]
|
|
public void Add_SingleNumber_ReturnsSameNumber()
|
|
{
|
|
var stringCalculator = new StringCalculator();
|
|
var actual = stringCalculator.Add("0");
|
|
Assert.Equal(0, actual);
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest[Unit testing C# with MSTest]
|
|
* https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-nunit[Unit testing C# with NUnit]
|
|
* https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-dotnet-test[Unit testing C# with xUnit]
|
|
|
|
=== Articles & blog posts
|
|
|
|
* https://www.everydayunittesting.com/2017/03/unit-testing-anti-pattern-not-asserting.html[Unit Testing anti-pattern]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
include::../message.adoc[]
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
=== on 2 May 2019, 14:44:07 Andrei Epure wrote:
|
|
This is implemented in https://github.com/SonarSource/sonar-dotnet/blob/7.13.0.8313/sonaranalyzer-dotnet/src/SonarAnalyzer.CSharp/Rules/TestMethodShouldContainAssertion.cs[TestMethodShouldContainAssertion ]
|
|
|
|
include::../comments-and-links.adoc[]
|
|
|
|
endif::env-github,rspecator-view[]
|