Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the return value for an IEnumerable class using NSubstitute

I have this domain:

public class ADomainClass
{
    public int Id { get; set; }
}

public interface IMyClass : IEnumerable<ADomainClass>
{
}

public class MyClass : IMyClass
{
    public IEnumerator<ADomainClass> GetEnumerator()
    {
        IList<ADomainClass> list = new List<ADomainClass>();
        //list = GetData...();

        foreach (var item in list)
        {
            yield return item;
        }
    }

    ...
}

and want to build the following test:

[Test]
public void TestSample()
{
    //Arrange
    IMyClass myclass = Substitute.For<IMyClass>();
    IList<ADomainClass> testdata = new List<ADomainClass>()
    {
        new ADomainClass(){ Id = 1, },
        new ADomainClass(){ Id = 2, },
        new ADomainClass(){ Id = 3, },
        new ADomainClass(){ Id = 4, },
    };
    int count = 0;

    myclass.ReturnsForAnyArgs(testdata); //How to set the "return" value?

    //Act
    foreach (ADomainClass item in myclass)
    {
        count++;
    }

    //Assert
    count.Should().Be(testdata.Count);
}

Setting the return value for a method is easy and would look like this:

myclass.GetData().Returns(data);

I can't remember how to set the return value when it is an enumerable class. I have solved this once before, but can't remember where I have used it.

like image 368
Peter Larsen 'CPH' Avatar asked May 17 '16 11:05

Peter Larsen 'CPH'


2 Answers

My problem was that NSubstitute stores the state of the enum, so if you use the Enumerator twice in the system under test, it will continue with the second element at the second time. I am using something like the code below as a workaround (using a lambda instead of returning the Enumerator, lines 1 + 2 are for demonstration only). I have only tested this with some Linq and foreach.

var bar = new List<string> { "a", "b", "c" };
var foo = Substitute.For<ICollection<string>>();
foo.GetEnumerator().Returns((ci) => { return bar.GetEnumerator(); });
like image 191
TvdH Avatar answered Oct 23 '22 01:10

TvdH


You just need to tell your substitute to return the enumerator from you test data:

myclass.GetEnumerator().Returns(testdata.GetEnumerator());
like image 26
forsvarir Avatar answered Oct 22 '22 23:10

forsvarir