How to clear previous expectations on an object?

ぃ、小莉子 提交于 2019-11-26 10:39:27

问题


I would like to set up a return value

_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(true);

but then in a specific test, override that expectation to return false.

Something like:

_stubRepository.ClearExpectations();  //<- this does not exist, I\'m just making something up
_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(false);

Notice, I do not want the expectation to return false on the second call, I want to override the first expectation.

This would help simplify my testing scenario greatly.


回答1:


There are three ways:

You can reset the expectations by using BackToRecord

I have to admit that I never really used it because it is awkward.

// clear expectations, an enum defines which
_stubRepository.BackToRecord(BackToRecordOptions.All);
// go to replay again.
_stubRepository.Replay();

Edit: Now I use it sometimes, it is actually the cleanest way. There should be an extension method (like Stub) which does it - I think it just got forgotten. I would suggest to write your own.

You can use Repeat.Any()

It 'breaks' the order of the stubbed definition and "overrides" previous definitions. But it's somehow implicit. I use it sometimes because it is easy to write.

_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false)
  .Repeat.Any();

You can create a new mock

Trivial, but explicit and easy to understand. It is only a problem if you want to keep plenty of definitions and only change one call.

_stubRepository = MockRepository.GenerateMock<IRepository>();
_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false);



回答2:


For these situations, I created a simple RinoMocks extention method to better show the intent of the stub and promote readability.

public static void OverridePrevious<T>(this IMethodOptions<T> options)
{
    options.Repeat.Any();
}

So instead of a cryptic call like the following that may require a comment:

[SetUp]
public void Setup()
{
    carStub.Stub(x => x.Model).Return("Model1");
    carStub.Stub(x => x.Model).Return("Model2");
}

[Test]
public void SomeTest()
{
    //Arrange
    //overrides previous stubs that were setup for the Model property
    carStub.Stub(x => x.Model).Return(null).Repeat.Any();

    //Act
    //Assert
}

You can get a more readable test that better shows the intent of the .Repeat.Any() calls:

carStub.Stub(x => x.Model).Return(null).OverridePrevious();



回答3:


For the sake of the community I'll add this to add to Stefan's list of options above:

If the return value needs to be changed frequently I find it clean and efficient to use a closure as follows.

bool returnValue = true;
_stubRepository.Stub(x => x.Contains(null)).IgnoreArguments().Do(new Func<bool>(() => {
    return returnValue;
}));

returnValue = false;
// Calls to Contains now return false;

returnValue = true;
// Calls to Contains now return true;

The lambda expression will be executed every time Contains is called and because we created a closure referencing returnValue, it will always look up the current value of returnValue.



来源:https://stackoverflow.com/questions/770013/how-to-clear-previous-expectations-on-an-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!