This is a migrated thread and some comments may be shown as answers.

AutoMock list dependency

3 Answers 37 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Nick
Top achievements
Rank 1
Nick asked on 23 Jul 2014, 08:48 AM
Hi, I've been having some trouble passing a list to a class that is the instance of a MockingContainer. 
01.using System.Collections.Generic;
02. 
03.namespace JustMock_AutoContainer
04.{
05.    public interface IWorker
06.    {
07.        void DoSomething();
08.    }
09. 
10.    public interface IService
11.    {
12.        string Moo { get; }
13. 
14.        void DoLotsOfThings();
15.    }
16. 
17.    public class Service : IService
18.    {
19.        private readonly IList<IWorker> workers;
20. 
21.        public Service(IList<IWorker> workers, string moo)
22.        {
23.            this.workers = workers;
24.            this.Moo = moo;
25.        }
26. 
27.        public string Moo { get; private set; }
28. 
29.        public void DoLotsOfThings()
30.        {
31.            foreach (var worker in this.workers)
32.            {
33.                worker.DoSomething();
34.            }
35.        }
36.    }
37.}

And the test class is:
01.using JustMock_AutoContainer;
02.using Microsoft.VisualStudio.TestTools.UnitTesting;
03.using System.Collections.Generic;
04.using Telerik.JustMock;
05.using Telerik.JustMock.AutoMock;
06.using Telerik.JustMock.Helpers;
07. 
08.namespace JustMock_AutoContainer_Tests
09.{
10.    [TestClass]
11.    public class ServiceTest
12.    {
13.        #region Fields
14.        private MockingContainer<Service> container;
15.        #endregion
16. 
17.        #region Test Configuration
18.        [TestInitialize]
19.        public void CreateTargetContainer()
20.        {
21.            this.container = new MockingContainer<Service>();
22.        }
23.        #endregion
24. 
25.        [TestMethod]
26.        public void DoLotsOfWork_TwoWorkers_AllWorkersCalled()
27.        {
28.            // Arrange
29.            var provider1 = StubWorker();
30.            var provider2 = StubWorker();
31.            var target = this.CreateTarget(provider1, provider2);
32. 
33.            // Act
34.            target.DoLotsOfThings();
35. 
36.            // Assert
37.            Assert.AreEqual("moo", target.Moo);
38.            provider1.Assert(p => p.DoSomething()); // Fails here :(
39.            provider2.Assert(p => p.DoSomething());
40.        }
41. 
42.        #region Support Methods
43.        private static IWorker StubWorker()
44.        {
45.            var dataTraceProvider = Mock.Create<IWorker>();
46.            return dataTraceProvider;
47.        }
48. 
49.        private IService CreateTarget(params IWorker[] providers)
50.        {
51.            this.container
52.                    .Bind<IList<IWorker>>()
53.                    .ToConstant((IList<IWorker>)providers);
54. 
55.            //TODO: fix line above; the list is not being picked up in the target.
56.            // JustMock seems keen on giving us a list with one and only one item in it, rather than
57.            // what we've registered above.
58.            this.container
59.                    .Bind<string>()
60.                    .ToConstant("moo");
61. 
62.            return this.container.Instance;
63.        }
64. 
65.        #endregion
66.    }
67.}

The registration on line 51 seems to be ignored.  Is there something else I should be doing?

3 Answers, 1 is accepted

Sort by
0
Accepted
Stefan
Telerik team
answered on 23 Jul 2014, 09:38 AM
Hello Nick,

NInject handles the injection of collections in a special case. Instead of treating it as a regular dependency type, it instead gathers all dependencies of the same type as the collection element types, creates a collection, fills it with these dependencies and passes this collection to the constructor.

You can employ this behavior by binding the individual IWorker instances, like so:
private IService CreateTarget(params IWorker[] providers)
{
    foreach (var provider in providers)
        this.container.Bind<IWorker>().ToConstant(provider);

Source: http://stackoverflow.com/questions/4588736/ninject-cascading-inection-with-ilist

Note that this is not behavior particular to JustMock, but to NInject. For issues unrelated to the injection of mocks, it is best to look for general NInject advice like in the above post.

I hope this fixes the issue for you.

Regards,
Stefan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Nick
Top achievements
Rank 1
answered on 09 Sep 2014, 03:16 PM
What if the class under tests modifies the list.  How could you verify the correct modifications were made? e.g. the CUT adds two new items
0
Stefan
Telerik team
answered on 10 Sep 2014, 08:21 AM
Hello Nick,

If you do not want multi-injection to kick in, then you can specify the parameter to inject directly, like so:

private IService CreateTarget(params IWorker[] providers)
{
    var providersArg = new ConstructorArgument("workers", providers);
    return this.container.Get<Service>(providersArg);
}
The above specifies that while resolving the "Service" instance, the constructor argument named "workers" should be given the "providers" instance.

Note that this mechanism works besides the .Instance property of the container. If you then get the value of the Instance property, it will construct a new instance of the Service class with the "workers" argument populated through multi-injection. You should be careful not to mix the usage of the two mechanisms in a given container instance.

Regards,
Stefan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
Tags
General Discussions
Asked by
Nick
Top achievements
Rank 1
Answers by
Stefan
Telerik team
Nick
Top achievements
Rank 1
Share this question
or