Recursive AutoMocking? Ninject interaction?

4 posts, 0 answers
  1. Micah
    Micah avatar
    6 posts
    Member since:
    Sep 2013

    Posted 17 Jul 2014 Link to this post

    01.public class Foo
    02.{
    03.    public Bar Bar;
    04. 
    05.    public Foo(Bar bar)
    06.    {
    07.        Bar = bar;
    08.    }
    09.}
    10. 
    11.public class Bar
    12.{
    13.    public IBaz Baz;
    14. 
    15.    public Bar(IBaz baz)
    16.    {
    17.        Baz = baz;
    18.    }
    19.}
    20. 
    21.public interface IBaz
    22.{
    23.    String GetString();
    24.}
    25. 
    26.[Test]
    27.public void when()
    28.{
    29.    var foo = new MockingContainer<Foo>();
    30.    foo.Arrange<IBaz>(baz => baz.GetString()).Returns("Rawr!");
    31. 
    32.    var actualResult = foo.Instance.Bar.Baz.GetString();
    33. 
    34.    Assert.AreEqual("Rawr!", actualResult);
    35.}

    Given the above code, a null reference exception is thrown on line 32.

    I am using NInject to do constructor dependency injection.  I have a large hierarchy of classes that take in their dependencies in their constructors as Foo and Bar do above.  I want all of my concrete classes to be instantiated and only have the interfaces get mocked.  In the above example, I want a real Bar constructed and a real Foo constructed but I want IBaz to be mocked.

    I am aware that in the above scenario I could just manually construct a Foo, passing in a manually constructed Bar, but in my scenario, the dependency hierarchy is large and complex and interfaces wrap all external (not my code calls).  Is there an easy way to tell the MockingContainer<Foo> that it should mock all interfaces but not mock any concrete classes (actually instantiate them).

    As I said, I am using Ninject to instantiate my classes and it does the right thing everywhere.  I understand that the automocking container is backed by Ninject.  Is there a way I can bind certain interfaces/classes to JustMock?  In the above example I could do something like:

    kernel.Bind<IBaz>().To<Mock<IBaz>>()?  That way I could just use Ninject to instantiate my object hierarchy, but tell it which interfaces I want it to bind to JustMock mocked instances.
  2. Micah
    Micah avatar
    6 posts
    Member since:
    Sep 2013

    Posted 17 Jul 2014 in reply to Micah Link to this post

    A little more spelunking and I found that I could do this:

    public class Foo
    {
        public Bar Bar;
     
        public Foo(Bar bar)
        {
            Bar = bar;
        }
    }
     
    public class Bar
    {
        public IBaz Baz;
     
        public Bar(IBaz baz)
        {
            Baz = baz;
        }
    }
     
    public interface IBaz
    {
        String GetString();
    }
     
    [Test]
    public void when()
    {
        var foo = new MockingContainer<Foo>();
        foo.Bind<Bar>().To<Bar>();
        foo.Arrange<IBaz>(baz => baz.GetString()).Returns("Rawr!");
     
        var actualResult = foo.Instance.Bar.Baz.GetString();
     
        Assert.AreEqual("Rawr!", actualResult);
    }

    This causes a real Bar to be constructed, while still mocking everything else.  This will unblock me, but it still requires me to manually go through and bind all of my concrete classes to themselves.  I would still like a way to tell JustMock to only mock interfaces, never concrete classes.
  3. DevCraft R3 2016 release webinar banner
  4. Micah
    Micah avatar
    6 posts
    Member since:
    Sep 2013

    Posted 17 Jul 2014 in reply to Micah Link to this post

    Another note to future searchers:
    foo.Bind<Bar>().ToSelf()
    That will cause foo to instantiate the real Bar, just like in my previous post and I believe it is a little more clear to the reader.
  5. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 18 Jul 2014 Link to this post

    Hello Micah,

    MockingContainer will always instantiate a mock for every dependency, unless there is an explicit binding telling it to do otherwise.

    container.Bind<T>().ToSelf()
    is indeed the correct way to tell it to not create a mock for T.

    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