chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes

Hi all,

I am working on a SharePoint 2016 project where I would like to fake all instances of type SPFieldUserValueCollection. SPFieldUserValueCollection itself inherits from List<SPFieldUserValue> and thus allows access to Linq extension methods like .Where() and .Select().

Mocking .Where() and .Select() quickly turns into an unreadable mess, thus I looked around in the docs and found .WillReturnCollectionValuesOf(). Considering the documentation:

Isolate. WhenCalled(() => <your_collection>).WillReturnCollectionValuesOf(<items>);

I thought I'd give it a try:
 

var fakeFieldUserValue = Isolate.Fake.Instance<SPFieldUserValue>();

var fakeFieldUserValueCollection = Isolate.Fake.Instance<SPFieldUserValueCollection>();

Isolate.WhenCalled(() => fakeFieldUserValueCollection)
            .WillReturnCollectionValuesOf(
                   new List<SPFieldUserValue> { fakeFieldUserValue }
             );

In this example, <your_collection> is equal to fakeFieldUserValueCollection. However, the code above throws an ArgumentOutOfRangeException:

Failure:

System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.

Parameter name: index

Stack Trace:

   at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)

   at System.ThrowHelper.ThrowArgumentOutOfRangeException()

   at System.Collections.Generic.List`1.get_Item(Int32 index)

   at _oJiwc1IhSkoCbhfIhmasuFjMTjP._02sePMelqT6pMKfF7IPNjRlbfBH`1._pVOOtbtDYsEhhHWcFc9z9Nx6Oqp._rdAcAO27axp3r80m0weVkSBMc8k()

   at TypeMock.ArrangeActAssert.ExpectationEngine._74WqWsXrKtdsupvOupEdcsRuDlD(Object , Boolean , Func`1 , Action , Action , Action , Boolean )

   at _oJiwc1IhSkoCbhfIhmasuFjMTjP._02sePMelqT6pMKfF7IPNjRlbfBH`1._Ovbb5hQAjT1KsRIMeW6DKXfq09E(IEnumerable )

   at UnitTests.Model.DemoTests.TheFaultyTest()

Best wishes
mzietlow

asked by mzietlow (630 points)
edited by mzietlow

2 Answers

0 votes
 
Best answer

Hi Mzietlow,

I found the issue in your test.
The issue is with the syntax of your WhenCalled statement.
The error message is referening to the object calling inside the statement, in your case: fakeFieldUserValueCollection.
It requires a call to a method/function of some kind with functionality like the following: object.func().
I understand the confusion from our docs as in the explanation there is no method calling, but in the example there is.

Therefore, the solution for your problem is replacing the WhenCalled Statement with the following:
Isolate.WhenCalled(() => yourCollection.Select(@int => @int + 1)).WillReturnCollectionValuesOf(replacementItems);

Please keep me posted on your progress.

Cheers,
Alon Sapozhnikov
Support Specialist.


 

answered by Alon_TypeMock (7.1k points)

Hi Alon,

thank you for the reply and your analysis of the issue :)

I would like to point out that a call to the .GetEnumerator() Method causes the same exception - although it is a method call:

Isolate.WhenCalled(() => yourCollection.GetEnumerator()).WillReturnCollectionValuesOf(replacementItems);

Best wishes,
mzietlow

Hi Mzietlow,

Can you send the example test please?

Cheers,
Alon Sapozhnikov.
Support Specialist.

Hi Alon, 

sure. The code is the same except for .GetEnumerator().

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TypeMock.ArrangeActAssert;

namespace TypemockMWE
{
    [TestClass]
    
public class ExampleUnitTest
    {
        [TestMethod, Isolated]
        
public void TestMethod1()
        {
            
// Arrange
            var replacementItems = new List<int> { 1, 2, 3, 4 };
            
var yourCollection = Isolate.Fake.Instance<ObjectInheritingFromList>();
            Isolate.WhenCalled(() => yourCollection.
GetEnumerator()).WillReturnCollectionValuesOf(replacementItems);

            // Act
            var result = yourCollection.Select(@int => @int + 1).ToList();

            // Assert
            var expected = new List<int> { 2, 3, 4, 5 };
            CollectionAssert.AreEqual(expected, result);
        }
    }


    
// This is (almost) equal to the class definition of SPFieldUserValueCollection
    public class ObjectInheritingFromList : List<int>
    {
        
// Not required for the minimal working example
    }
}

0 votes

Hi Mietlow,

Can you please share with us the logs produced when running this test,
you can enable the logs thorugh the Configuration tool or the extension menu in VS.
Also, if it's possible to create a sample project that reproduces the issue it will be very helpfull.
I've sent you a personal email so you could send us the following details in a more comfarble way.

Please keep us posted.
Cheers,
Alon Sapozhnikov
Support Specialist.

 

answered by Alon_TypeMock (7.1k points)

Hi Alon,

thank you for the fast reply. I have tried to send you minimal working example (MWE) project per mail. Unfortunately, the mail got intercepted by some obscure corporate policy. As an alternative, I have posted the MWE below.

As for logs, TypeMock allows to record Mocking, SmartRunner, Test Suggestions and Sandbox logs. Considering that the log folder quickly explodes in size, which logs do you require?

MWE for reference:

I have created a UnitTest Project via VS2017 with the following dependencies:
.NET Framework 4.6.1,
TypeMock 9.0.3.0,
and MSTest 1.3.2 which was the default chosen by VS2017

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TypeMock.ArrangeActAssert;

namespace TypemockMWE
{
    [TestClass]
   
public class ExampleUnitTest
    {
        [TestMethod, Isolated]
       
public void TestMethod1()
        {
           
// Arrange
            var replacementItems = new List<int> { 1, 2, 3, 4 };
           
var yourCollection = Isolate.Fake.Instance<ObjectInheritingFromList>();
            Isolate.WhenCalled(() => yourCollection).WillReturnCollectionValuesOf(replacementItems);

            // Act
            var result = yourCollection.Select(@int => @int + 1).ToList();

            // Assert
            var expected = new List<int> { 2, 3, 4, 5 };
            CollectionAssert.AreEqual(expected, result);
        }
    }


   
// This is (almost) equal to the class definition of SPFieldUserValueCollection
    public class ObjectInheritingFromList : List<int>
    {
       
// Not required for the minimal working example
    }
}

Hi Mzietlow,

Thank you for the sample project, we will dig into it and try to reproduce the issue on our side.
As for the logs, for this case all we need is the Mocking logs.
You can send them to the mail I sent you.

Cheers,
Alon Sapozhnikov.
Support Specialist.

...