سؤال

I am learning to use/perform/write tests for my code and started using FakeItEasy for my fake/mock objects, now I have encountered a problem :

I have the following class that implements IEnumerable and internal class that implements IEnumerator (not complete code below) :

public interface IEnumarableString : IEnumarable
{ }

public class AdvancedString : IEnumarableString
{
    private string[] _strings;
    private class StringEnumerator : IEnumerator
    {
            private IEnumerator GetEnumerator()
            {
                return (IEnumerator)this;
            }

            public object Current {get; set;}

            public bool MoveNext()
            {
                _position++;
                return _position < strings.Length;
            }

            public void Reset()
            {
                _position = -1;
            }
    }
    public IEnumerator GetEnumerator()
    {
           return new StringEnumerator(_strings);
    }
}

I want to use FakeItEasy on my tests and "fake" its iterative behavior, I tried the following code but it does not iterate through itself when it needs to (just skip the foreach like there are no elements) :

IEnumarableString stringFake = A.Fake<IEnumarableString>();

A.CallTo(() => stringFake.GetEnumerator().MoveNext()).Returns(false).Once();
A.CallTo(() => stringFake.GetEnumerator().MoveNext()).Returns(true).Once();

tried to search the net for example but could not find any. for now my question is how do I configure the stringFake.GetEnumerator() to return the right object so the iteration will work or am I doing something wrong here ?

Any help would be appreciated.

Thanks

هل كانت مفيدة؟

المحلول

If you can't just provide a concrete IEnumerable<string> as @TimS suggested, because you need extra functionality, I think I have a solution for you.

I think the problem you're having is because the unconfigured GetEnumerator() on stringFake will always return a new enumerator (FakeItEasy will have unconfigured properties always return the same value, but unconfigured methods do not cache their return values and will give new values easy time).

If you configure it to return a particular enumerator, you should have better luck. I don't have a compiler with me, but something like:

IEnumarableString stringFake = A.Fake<IEnumarableString>();
IEnumerator<string> fakeEnumerator = A.Fake<IEnumerator<string>>();

A.CallTo(() => stringFake.GetEnumerator()).Returns(fakeEnumerator);
A.CallTo(() => fakeEnumerator.MoveNext()).ReturnsNextFromSequence(true, false);

Or something. Note that you'll also have to set up the behaviour on fakeEnumerator.Current. There is already a question that deal with faking an enumerator. You should be able to see it for additional details—Faking an enumerator in FakeItEasy

نصائح أخرى

it seems unnatural to be faking ones own objects, I typically fake only dependencies that I have no control over. In a situation like this, I would use a constructor that lets me pass in a ready made array of strings. Alternatively, I would make a different implementation of IEnumerableString with the test behaviour I wanted.

If AdvancedString is the unit under test, then simply give it some test data to work on, don't try to fake the enumerable, since that is part of what you are testing.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top