Kyle L.
Kyle L.

Reputation: 634

Dependency Injection with Moq and AutoMoq (AutoFixture) w/ xUnit

I'm writing this because I've tried for a bit to figure this out myself with no luck. Every example I can find for whatever reason seems to suggest that this just works out of the box but whenever I try to do the same, I always get errors. Basically, I have a controller with two properties that are injected via. DI, let's say

public class SomeController
{
    private ISomeInterface _i;
    private MyConfig _c;

    public SomeController(ISomeInterface i, MyConfigContext cxt) // Where cxt is Type of DbContext
    {
        _i = i;
        _c = cxt.Configs.FirstOrDefault();
    }

    public OkResult PostModel(SomeModel c)
    {
        // Do things
        return Ok();
    }
}

And in my tests using xUnit, Moq & AutoFixture I'm trying to avoid having to manually instantiate dependencies B and C:

public class SomeControllerTests
{
    private MyDbContext _cxt;
    private Fixture _fixture;

    public SomeControllerTests()
    {
        _cxt = GetCxt() // GetCxt() just returns a context instance, nothing special
       _fixture = new Fixture();
       _fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true });
       _fixture.Customizations.Add(
          new TypeRelay(
              typeof(ISomeInterface),
              typeof(SomeConcreteClass)
          )
       );
    }

    [Fact, AutoData]
    public void PostStatus_ReturnsOk_GivenValidRequest()
    {
        SomeController c = _fixture.Create<SomeController>();
        SomeModel m = _fixture.Create<SomeModel>();
        var result = c.PostModel(m);

        Asset.IsType<OkResult>(result);
    }
}  

With the above I am getting a NotImplementedException when I run the tests and it won't tell me what exactly is not being implemented so I have no way of knowing what the issue is. I must be missing something in the docs. I want to use AutoFixture to make my tests more durable but so far it has been a pain trying to use it. I really don't want to have to mock/stub my entire app manually just to run a test. I would ideally like to use the syntax shown in the AutoFixture docs where you put your test-relevant instances in the params of the test and they are created for you but I haven't had any luck with it, like...

[Theory, AutoData]
SomeTestMethod(SomeController c, SomeModel m)
{
    var result = c.PostModel(m);

    Assert.IsType<OkResult>(result);
}

Thanks for Reading (:

Upvotes: 2

Views: 2501

Answers (1)

Ssss
Ssss

Reputation: 152

Try to add next attribute and use it instead of AutoData.

using AutoFixture.AutoMoq;
using AutoFixture.Xunit2;

namespace Cats
{
    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute()
            : base(() => new Fixture().Customize(new AutoMoqCustomization()))
        {
        }
    }
}

[Theory, AutoMoqData]
SomeTestMethod(SomeController c, SomeModel m)
{
    var result = c.PostModel(m);

    Assert.IsType<OkResult>(result);
}

Upvotes: 1

Related Questions