Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve method doesn't register created instance #19

Open
nimbusparis opened this issue Apr 3, 2020 · 6 comments
Open

Resolve method doesn't register created instance #19

nimbusparis opened this issue Apr 3, 2020 · 6 comments

Comments

@nimbusparis
Copy link

While updating AutoFake from v 5.x to 6.0.0, many of my tests failed. It seems that the Resolve method for mock doesn't register it and I need to call Provide with the returned instance:

var instance = autoFake.Resolve<IInterface>();
var sut = autoFake.Resolve<SystemUnderTest>();

don't work, instance of IInterface injected in sut if not the same.

var instance = autoFake.Resolve<IInterface>();
autoFake.Provide(instance);
var sut = autoFake.Resolve<SystemUnderTest>();

Works

Could you have a look?

@blairconrad
Copy link
Contributor

@nimbusparis, that seems to be the proper way, according to the Configuring Specific Dependencies topic. If your first example ever worked, could you please provide the version numbers of

  1. Autofac
  2. Autofac.Extras.FakeItEasy
  3. FakeItEasy

for which it worked and for which it doesn't?

@alistairjevans
Copy link
Member

Just a tip, based on our recent experience updating the Moq integration to be compatible with Autofac v5, it may be worth looking at it as an example. It took us a couple of variations to get right.

We did away with the Provide method as it is not really compatible with the immutable registry, and replaced the ACTNARS implementation with some sensible similar behaviour inside the custom handler.

@nimbusparis
Copy link
Author

nimbusparis commented Apr 3, 2020

Packages versions:
FakeItEasy Version="6.0.0-beta.1" => Version="6.0.0"
Autofac Version="4.9.4" => Version="5.1.2"
Autofac.Extras.FakeItEasy Version="5.0.1" Version="6.0.0"

Well, I've try to make a simple sample but it doesn't fail with new version of AutoFake.

@blairconrad
Copy link
Contributor

@nimbusparis, if it doesn't fail with the new version of Autofac.Extras.FakeItEasy, am I right in understanding that you can move forward with your project?

@nimbusparis
Copy link
Author

No, I've tried to create a sample with old packages and new and didn't make it fails.
Btw, in my project, updating only AutoFac packages (and not Autofac.Extras.FakeItEasy) break all my unit tests. When I update Autofac.Extras.FakeItEasy also, only a few of them still fails.
But I can fix most of them by adding autoFake.Provide(instance);
I will try to find what is the breaking change in AutoFac that break everything in my tests.

@nimbusparis
Copy link
Author

nimbusparis commented Aug 13, 2020

Hello, I've made other tests and I've found what fails. When you inject a concrete class in your system under test and provide an instance to autoFake, it inject different instance of the one returned before the SUT is created. See the code below:

namespace TestAutoFake
{
    public class UnitTest1
    {
        [Fact]
        public void Test1()
        {
            using var autoFake = new AutoFake();
            // Arrange
            var serviceFake = autoFake.Resolve<IService>();
            // Uncomment this line to make the test pass
            //autoFake.Provide(serviceFake);
            A.CallTo(() => serviceFake.GetValue()).Returns(10);
            autoFake.Provide(new Concrete() {Value = 20});
            var target = autoFake.Resolve<Target>();
            // Arrange
            var result = target.Execute();

            // Assert
            Assert.Equal(30, result);
        }
    }

    public class Target
    {
        private readonly IService _service;
        private readonly Concrete _concrete;

        public Target(IService service, Concrete concrete)
        {
            _service = service;
            _concrete = concrete;
        }

        public int Execute()
        {
            return _service.GetValue() + _concrete.Value;
        }
    }

    public class Concrete
    {
        public int Value { get; set; }
    }

    public interface IService
    {
        int GetValue();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants