I have the following sample test code
public Stage Test(Stage Stage)
{
var StartStage = StageRepository.Single(x => x.Order == 1);
var EndStage = StageRepository.Single(x => x.Order == 5);
var ErrorStage = StageRepository.Single(x => x.Name == "Error");
if (Stage == StartStage)
{
return EndStage;
}
else
{
return ErrorStage;
}
}
And I am trying to test it using the following unit test
[TestMethod]
public void XXXTest()
{
//// Arrange
var AutoMocker = new RhinoAutoMocker<StageService>(MockMode.AAA);
MockRepository mockRepository = new MockRepository();
var MockStageRepository = AutoMocker.Get<IRepository<Stage>>();
Stage StartStage = mockRepository.Stub<Stage>();
StartStage.Order = 1;
Stage EndStage = mockRepository.Stub<Stage>();
EndStage.Order = 5;
Stage ErrorStage = mockRepository.Stub<Stage>();
ErrorStage.Name = "Error";
System.Linq.Expressions.Expression<Func<Entities.Stage, bool>> StartParam = x => x.Order == 1;
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Is.Equal(StartParam)))
.Return(StartStage);
System.Linq.Expressions.Expression<Func<Entities.Stage, bool>> EndParam = x => x.Order == 1;
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Is.Equal(EndParam)))
.Return(EndStage);
System.Linq.Expressions.Expression<Func<Entities.Stage, bool>> ErrorParam = x => x.Order == 1;
MockStageRepository
.Stub(x => x.Single(Arg<System.Linq.Expressions.Expression<Func<Entities.Stage, bool>>>.Is.Equal(ErrorParam)))
.Return(ErrorStage);
StageService StageService = AutoMocker.ClassUnderTest;
//Act
var ReturnStage = StageService.Test(StartStage);
//Assert
Assert.AreEqual(ReturnStage, EndStage);
}
However this is not working as it is not returning anything when I call StageRepository.Single(). If I change the stub code to ignore the argument then it does return something but it will be the same object returned for each call to Single() which I don’t want.
Is it possible to configure RhinoMocks in such a way as to return different objects from a stub depending on the lambda that is passed into it?
I think the root of your problem is that equality on the
Expression<Func<T,U>>type is performed by reference rather than value. That means your telling Rhino Mocks to look for instances of expressions created in the test rather than the ones created in the code your testing.Two possible approaches come to mind:
One would be to provide a way to pass the lambda expressions in to the Stage class from the test, so that when the argument checks happen they are working against the same instances.
Maybe something like:
The inverse of this would also work, i.e. provide the
Expressionobjects as fields/properties that can be accessed by you’re test, and then use those when setting up your mock:Another option would be to use the
Matchesmethod onArgsto see if the argument checks theStageobject state correctly. This would require creating someStageobjects in your test that would match the criteria:The call to
Compile()is a little jarring, but since you’re dealing with an Expression and not a straight-up lambda, you’ve got to compile it in order to evaluate it.Now, if a
Stageis something that is hard to create, then you may need to create a Mock/Stub of one (or use you’reStartStage) and have it return 1 from theOrderproperty (in the case of the StartStage anyway).There are probably some others I’m not thinking of at the moment as well.