AutoMock list dependency

4 posts, 1 answers
  1. Nick
    Nick avatar
    2 posts
    Member since:
    Jul 2014

    Posted 23 Jul 2014 Link to this post

    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?
  2. Answer
    Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 23 Jul 2014 Link to this post

    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.

     
  3. DevCraft R3 2016 release webinar banner
  4. Nick
    Nick avatar
    3 posts
    Member since:
    Jan 2012

    Posted 09 Sep 2014 Link to this post

    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
  5. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 10 Sep 2014 Link to this post

    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.

     
Back to Top