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
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
I am having a problem with collections

I have the following class to test

This class has a web service call to getSavedFilters that returns an array of RemoteFilter. The problem is I get the corect number of elements in the array returened but they are empty when I debug into the class.

Here is my test class. Any ideas what I am doing wrong.


var filters = new RemoteFilter[1];
var filter = new RemoteFilter();
filter.id = "Fred";
filters[0] = filter;

var JiraAccessorMock = Isolate.Fake.Instance<JiraAccessor>();
Isolate.WhenCalled(() => JiraAccessorMock.WS.getSavedFilters("")).WillReturn(filters);

var container = new UnityContainer().RegisterInstance<JiraAccessor>(JiraAccessorMock);
var jiraIssues = container.Resolve<JiraIssues>();

// Perform a Get Users By Filter Test
List<Issue> issues = jiraIssues.GetIssuesByFilter("Test");




        public List<Issue> GetIssuesByFilter(string filterName)
        {
            RemoteFilter[] filters = Accessor.WS.getSavedFilters(Accessor.Token);

            // Locate Filter ID
            string filterId = null;
            foreach (RemoteFilter filter in filters)
            {
                if (filter.name.Equals(filterName))
                {
                    filterId = filter.id;
                    break;
                }
            }

            var issues = new List<Issue>();
            if (filterId != null)
            {
                var remoteIssues = Accessor.WS.getIssuesFromFilter(Accessor.Token, filterId);
                foreach (var issue in remoteIssues)
                {
                    var iss = new Issue {ID = issue.id, Key = issue.key};
                    issues.Add(iss);
                }
            }
            return issues;
        }
    }
asked by SwissSteve (800 points)

10 Answers

0 votes
Hi,
I think you are missing the following:
filters[0] = filter;
answered by error (6.6k points)
0 votes
No, I have this line after initing the object, line 4.
Or am I doing something daft :oops:
answered by SwissSteve (800 points)
0 votes
Hi Steve,

A couple of things about your test:
1. why use Unity to register and fetch your fake object? you can avoid the call to the JiraAccessor altogether by faking the static call Accessor.WS.getSavedFilters().
2. The first 5 lines can be more compact - example below.
3. Did you forget setting your filter's name to "Test" so it will be picked out by the code under test?

This is how I would write this test:
// create a fake filter with an id and name and put it in the result of getSavedFilters()
Isolate.WhenCalled(() => Accessor.WS.getSavedFilters(null)[0].Id).WillReturn("TestId");
Isolate.WhenCalled(() => Accessor.WS.getSavedFilters(null)[0].Name).WillReturn("TestName");

// if you cannot instantiate JiraIssues use Unity to resolve it for you. However, eliminating dependency in Unity would make the test
// less brittle
var target = new JiraIssues();
List<Issue> result = target.GetIssuesByFilter("TestName");

// verify we got the correct issues list
Assert.AreEqual(1, result.Count);
Assert.AreEqual("TestId", result[0].ID);


Please let me know if this works.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Firstly, thanks for the help.

I tried your example and it complies but does not run. I get an index out of bounds exception for the first WhenCalled statement. Not being to familiar with Lambta expression syntax, can you tell me how to init the array you are assigning to in the example?

You are correct regarding Unity, I was just playing with IoC and wondering if TypeMock would work with it.
answered by SwissSteve (800 points)
0 votes
Steve,

You shouldn't have to initialize the array - the call chain in the lambda expression isn't really called, but instead analyzed and recorded by Isolator. The exception comes from some other reason. One I could think of is Accessor.WS being a field - is that the case?

Can you post some more code with the classes under test, or alternatively send a solution with the failing test to support at typemock.com?

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
You are correct WS in the real world references an instance of the Web Service.

Off course i will send you some code tonight but what else must I do to handle the WS property?
answered by SwissSteve (800 points)
0 votes
Here is the Accessor class that is passed into the constructor of the class under test. WS is a property of this class and is initialized with a reference to the web service in question.

I also added the following to init the WS

Accessor.WS = Isolate.Fake.Instance<JiraSoapServiceService>();

But still the same issue.

I have also mailed the solution as requested.



Look forward to your recommendations

   public class JiraAccessor
    {
        private readonly ILog logger = LogManager.GetLogger(typeof(JiraAccessor));
        public ILog Logger
        {
            get
            {
                return logger;
            }
        }

        public JiraSoapServiceService WS { get; set; }
        public  string Token { get; set; }

        public JiraAccessor(string location, string username, string password)
        {
            try
            {
                Logger.Info("Fix how we set the web service location");

                WS = new JiraSoapServiceService();
                string loc = location + "/rpc/soap/jirasoapservice-v2";
                WS.Url = loc;
                Token = WS.login(username, password);
            }
            catch (Exception ex)
            {
                Logger.Error("Enable to Access the Jira Server : " + ex.Message);
            }
        }

        public Hashtable GetFilters()
        {
            RemoteFilter[] filters = WS.getSavedFilters(Token);

            var table = new Hashtable();
            foreach (var filter in filters)
            {
                table.Add(filter.id, filter.name);
            }

            return table;
        }
    }
answered by SwissSteve (800 points)
0 votes
Did some more debugging and noticed that after the call to

Accessor.WS = Isolate.Fake.Instance<JiraSoapServiceService>();

If I look at WS in the debugger and inspect its content after the call then all methods are assigned with null, is this normal?

I even tried this

var Accessor = Isolate.Fake.Instance<JiraAccessor>();
Isolate.WhenCalled(() => Accessor.WS).WillReturn(Isolate.Fake.Instance<JiraSoapServiceService>());
Isolate.WhenCalled(() => Accessor.WS.getSavedFilters(null) [0].id).WillReturn("TestId");
Isolate.WhenCalled(() => Accessor.WS.getSavedFilters(null) [0].name).WillReturn("TestName");

Still failed on line 3 with index out of bounds exception

I am at a bit of a loss to know where to go from here


answered by SwissSteve (800 points)
0 votes
Hi Steve

We got the solution you sent and it reproduces the problem.
We will investigate the issue and get back to you as soon as possible.
answered by ohad (35.4k points)
0 votes
Steve & all,

This issue is related to a known Isolator limitation - faking mscorlib types. The getSavedFilters() call returns an array, which is an mscorlib type. Putting this is a faked call chain causes an attempt to fake the behavior of the array, which leads to the (confusing :oops:) error message.

A workaround for this is setting the return value of getSavedFilters() to return an array of fake objects; this way we don't try to fake the array behavior, but rather determine the array that will be returned:
var fakeFilter = Isolate.Fake.Instance<RemoteFilter>();
fakeFilter.id = "TestId";
fakeFilter.name = "TestName";
Isolate.WhenCalled(() => Accessor.WS.getSavedFilters(null)).WillReturn(new[] { fakeFilter });


Please let me know if this helped. In the meanwhile, we will work to improve the error message for an upcoming version.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
...