I'm unit testing the following method and I expect ArgumentOutOfRangeException
to be thrown. Instead gridTrading.GridLevels().As<double[]>()
returns null for whatever reason. It basically swallows the exception. How do I fix it by keeping the return type as IEnumerable<double>
and not converting it to List<double>
? Btw, I added .As<double[]>()
to prevent multiple enumeration.
Lastly, do you think I'm wrong by trying to keep it IEnumerable<double>
?
[Fact]
public void GridLevels_ShouldThrow_WhenGivenInvalidGridType()
{
// Arrange
const double lowerLimit = 2000;
const double upperLimit = 10000;
const int gridCount = 4;
const int gridType = 4;
var gridTrading = new GridTrading(lowerLimit, upperLimit, gridCount, (GridType)gridType);
// Act
var action = new Action(() => gridTrading.GridLevels().As<double[]>());
// Assert
action.Should().Throw<ArgumentOutOfRangeException>().WithMessage("Grid type must be valid");
}
// The method I test
public IEnumerable<double> GridLevels()
{
switch (_gridType)
{
case GridType.Arithmetic:
foreach (var level in CalculateArithmetic())
{
yield return level;
}
break;
case GridType.Geometric:
foreach (var level in CalculateGeometric())
{
yield return level;
}
break;
default:
throw new ArgumentOutOfRangeException(nameof(_gridType), "Grid type must be valid");
}
IEnumerable<double> CalculateArithmetic()
{
var step = (_upperLimit - _lowerLimit) / _gridCount;
for (var i = 0; i <= _gridCount; i )
{
var price = _lowerLimit step * i;
yield return price;
}
}
IEnumerable<double> CalculateGeometric()
{
var step = Math.Pow(_upperLimit / _lowerLimit, 1.0 / _gridCount);
for (var i = 0; i <= _gridCount; i )
{
var price = _lowerLimit * Math.Pow(step, i);
yield return price;
}
}
}
I know I could make GridLevels a List<double>
instead IEnumerable<double>
which would make it throw for real but I don't wanna do that.
public List<double> GridLevels()
{
var list = new List<double>();
switch (_gridType)
{
case GridType.Arithmetic:
list.AddRange(CalculateArithmetic());
break;
case GridType.Geometric:
list.AddRange(CalculateGeometric());
break;
default:
throw new ArgumentOutOfRangeException(nameof(_gridType), "Grid type must be valid");
}
return list;
IEnumerable<double> CalculateArithmetic()
{
var step = (_upperLimit - _lowerLimit) / _gridCount;
for (var i = 0; i <= _gridCount; i )
{
var price = _lowerLimit step * i;
yield return price;
}
}
IEnumerable<double> CalculateGeometric()
{
var step = Math.Pow(_upperLimit / _lowerLimit, 1.0 / _gridCount);
for (var i = 0; i <= _gridCount; i )
{
var price = _lowerLimit * Math.Pow(step, i);
yield return price;
}
}
}
CodePudding user response:
You're GridLevels
method returns a lazy-evaluated IEnumerable<double>
which FA will never explicitly enumerate unless you use the Enumerating
extension methods. Instead, you're using the As
extension method. That one will try to cast your enumerable to double[]
, which isn't possible. In that case, As
will return default(double[])
. In other words, your code isn't being executed.