Why does the following test fail using Mbunit and Rhino mocks?
I am playing around with MbUnit and Rhino Mocks and made a simple test. It may be poorly designed code, but I am more focused on just seeing if I can get the test to pass. Basically, When the engine light of a car is on, the car should an oil change. Here is code:
public interface ICar
{
开发者_StackOverflow bool EngineLight { get; set; }
void GetOilChange();
bool CheckEngineLight(ICar car);
}
public class Car : ICar
{
public bool EngineLight { get; set; }
public void GetOilChange()
{
}
public bool CheckEngineLight(ICar car)
{
if (car.EngineLight)
GetOilChange();
return true;
return false;
}
}
[TestFixture]
public class CarTests
{
[Test]
public void WhenEngineLightIsOnGetOilChange()
{
var carMock = MockRepository.GenerateMock<ICar>();
carMock.Stub(x => x.EngineLight).Return(true);
Assert.AreEqual(true, new Car().CheckEngineLight(carMock)); //This passes
carMock.AssertWasCalled(x => x.GetOilChange()); //This fails
}
}
In this method:
public bool CheckEngineLight(ICar car)
{
if (car.EngineLight)
GetOilChange();
return true;
return false;
}
you are calling GetOilChange(); on the object you are testing, and not on the mock you passed as a paramter. Hence this method indeed wasn't called on the mock. I guess you want to have this:
public bool CheckEngineLight(ICar car)
{
if (car.EngineLight)
{
car.GetOilChange();
return true;
}
return false;
}
First off, this code has a bug. Add in the {} around the IF:
public bool CheckEngineLight(ICar car)
{
if (car.EngineLight)
{
car.GetOilChange();
return true;
}
return false;
}
The reason it fails is because you are calling new Car().CheckEngineLight ... and the new Car() is calling GetOilChange ... the carMock is not calling GetOilChange. Change the code to car.GetOilChange()
(see it in the code above).
The fact that you are passing a Car object into a method on the Car Object is very confusing. Why not change the code to this:
public class Car : ICar
{
public bool EngineLight { get; set; }
public void GetOilChange()
{
}
public bool CheckEngineLight()
{
if (EngineLight)
{
GetOilChange();
return true;
}
return false;
}
}
Change your test to:
[Test]
public void WhenEngineLightIsOnGetOilChange()
{
var carMock = MockRepository.GenerateMock<ICar>();
carMock.Stub(x => x.EngineLight).Return(true);
Assert.AreEqual(true, carMock.CheckEngineLight());
carMock.AssertWasCalled(x => x.GetOilChange());
}
}
Your test is buggy, that's all. Change
GetOilChange(); // calls the car instance, not the mock, your
// AssertMethodCalled will never be true
to
car.GetOilChange(); // calls the mock you passed in
Incidentally, this is probably more idiomatic for Rhino:
public interface ICar
{
bool EngineLight { get; set; }
void GetOilChange();
bool CheckEngineLight();
}
public class Car : ICar
{
public bool EngineLight { get; set; }
public virtual void GetOilChange()
{
}
public virtual bool CheckEngineLight()
{
if (EngineLight)
{
GetOilChange();
return true;
}
return false;
}
}
[TestFixture]
public class CarTests
{
[Test]
public void WhenEngineLightIsOnGetOilChange()
{
MockRepository mocks = new MockRepository();
Car car;
using (mocks.Record())
{
car = mocks.PartialMock<Car>();
car.EngineLight = true;
car.Expect(x => x.GetOilChange())
.Repeat.Once()
.Message("Should have called GetOilChange");
}
using (mocks.Playback())
{
var res = car.CheckEngineLight();
Assert.IsTrue(res);
}
}
}
精彩评论