How do I test a method on a class that calls another method in the same class using Rhino Mocks
I have a class that solves an equation using an approximation, evaluates the approximation and then refines the approximation(bisection method), rinse and repeat until the answer appears. In order to do that it needs to go and get various values from other complex classes. It also need to repeatedly call a method within itself to work out how to change the guess before running through the method again. I've managed to test the calculate method:
protected double GRPY(double royGuess, ReductionOnYield redOnYield )
{
log.LogEnter();
double d1 = 0D;
double d2 = 0D;
double growth = 0D;
double regularPremiumInMonthm = 0D;
double termSurrenderValue = Convert.ToDouble(illus.GetCashInValue(redOnYield.Month) * GetFundStreamSplit(redOnYield, redOnYield.Month));
for (int i = 1; i <= redOnYield.Month; i++)
{
regularPremiumInMonthm = Convert.ToDouble(illus.RegularPremium.PremiumAmount * Convert.ToDecimal(GetFundStreamSplit(redOnYield, i)));
d1 = (1 + royGuess);
d2 = (redOnYield.Month - (i - 1)) / 12D;
growth = growth + Convert.ToDouble(regularPremiumInMonthm) * Math.Pow(d1, d2);
}开发者_开发知识库
double gRoy = ((termSurrenderValue - growth))/termSurrenderValue;
log.LogExit();
return gRoy;
}
However I now want to test the guess new approximation method which calls the calculate method:
protected double SetNewMidPoint(double midPoint, double gStartLow, double gStartHigh, double gMidPoint, ReductionOnYield redOnYield)
{
log.LogEnter();
if ((gStartLow * gStartHigh) > 0)
{
startLow = 0.001D;
startHigh = 0.07D;
midPoint = (startHigh - startLow)/2 + startLow;
gStartLow = GRPY(startLow, redOnYield);
gStartHigh = GRPY(startHigh, redOnYield);
gMidPoint = GRPY(midPoint, redOnYield);
if((gStartLow > 0) && (gStartHigh > 0))
{
midPoint = 0.07D;
}
if ((gStartLow < 0) && (gStartHigh < 0))
{
midPoint = 0D;
}
}
if((gStartLow * gMidPoint) < 0)
{
startHigh = midPoint;
midPoint = (startHigh - startLow)/2 + startLow;
}
if((gStartLow * gMidPoint) > 0)
{
startLow = midPoint;
midPoint = (startHigh - startLow)/2 + startLow;
}
log.LogExit();
return midPoint;
}
This is the test but its obviously not working. I know I'm missing something (possibly something massively fundamental about Rhino Mocks)
[TestMethod()]
public void SetNewMidPointGStartLowTimesGStartHighGreaterThanZeroTest()
{
var quote = MockRepository.GenerateStub<EQuote>();
double growthRate = 0.07;
quote.Request = new Request();
var illustration = MockRepository.GenerateStub<Illustration>(quote, growthRate);
var target = MockRepository.GenerateMock<RegularPremiumReductionOnYieldCalculator_Accessor>(illustration);
double gStartLow = 0.1F;
double gStartHigh = 0.1F;
double gMidPoint = 0.1F;
double startLow = 0F;
double startHigh = 0F;
double midPoint = 0F;
var redOnYield = MockRepository.GenerateStub<ReductionOnYield>(1);
target.Stub(x => x.GRPY(0.001D, redOnYield)).Return(0.07D).Repeat.Once();
target.Stub(x => x.GRPY(0.07D, redOnYield)).Return(0.07D).Repeat.Once();
target.Stub(x => x.GRPY(midPoint, redOnYield)).Return(0).Repeat.Any();
double actual = target.SetNewMidPoint(midPoint, gStartLow, gStartHigh, gMidPoint, redOnYield);
double expected = 0.07D;
Assert.AreEqual(expected, actual);
}
Usually when writing a test proves to be very difficult it means that you should split you class into smaller classes. In your case my first guess is that your calculate method should be in one class, and your approximate method (the one that uses the calculate method) should be in a different class. The second class would then use the first class. In your tests you could mock the test class, so that you can easily control what the calculate method will return.
精彩评论