Suppose we have a Calculator
with a divide method throwing error if the denominator is 0:
public class Calculator
{
public double Divide(int x, int y)
{
if (y == 0)
{
throw new ArgumentOutOfRangeException(paramName: nameof(y), message: CalculatorErrorMessages.DenominatorShouldNotBeZero);
}
return (double)x / y;
}
}
public static class CalculatorErrorMessages
{
public static string DenominatorShouldNotBeZero = "Denominator should not be zero.";
}
And here's the unit test which tries to test the raise of the exception:
public class CalculatorUnitTest
{
[Fact]
public void Test1()
{
var calculator = new Calculator();
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => calculator.Divide(1, 0));
Assert.Contains(CalculatorErrorMessages.DenominatorShouldNotBeZero, ex.Message);
}
}
Stryker.NET reports the exception message survives mutation:
But that mutation survival is not an actual problem, since both the unit test code and the app code generate the exception message in the same way. I don't want to duplicate and maintain error messages in the app and the unit test.
For this, I could make Stryker ignore mutations on CalculatorErrorMessages
but it does not sound like a good idea. Stryker will not catch a situation where the unit test does not handle error messages like it should. For example, let's say I add a new method DivideV2
in the Calculator which also throws an exception, and in the unit-test, instead of using the actual error message constant, I hard-code the expected error message:
[Fact]
public void Test2()
{
var calculator = new Calculator();
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => calculator.DivideV2(1, 0));
Assert.Contains("Denominator should not be zero.", ex.Message);
}
In this situation, the mutation survival should really not be ignored.
How can I make in such a way Stryker:
- Does not show me 'false' mutations survivals
- Still make my code unit tested by mutations
- Not duplicate the error message strings across the app and unit-test