-
Notifications
You must be signed in to change notification settings - Fork 21
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
4.1.0 Update using System.MissingException. The lazily-initialized type does not have a public, parameterless constructor. #15
Comments
Have you tried Autofac.Extras.Moq 4.2.0? |
If it still fails in 4.2.0, can you update your unit test to be something we could run?
Also, include the exception information here so we can see what's actually breaking. If we both can't run the test and we don't know what the exception is, we're stuck. |
I think I'm running into a similar issue. With v4.0.0, I could use mock.Create() on a class that had a Func that returned an object that only had a parameterless constructor. Since AutoMock couldn't resolve concrete types, it would not try to mock and pass resolution on to Autofac. Autofac could figure out what to do because AutoMock has Autofac auto-register all concrete types. Since v4.1 added the ability to resolve concrete classes, AutoMock no longer passes these on to Autofac and instead tries to mock the object. This fails since Moq (Well, Castle.Proxy) needs a parameterless constructor to create the mock. This same behavior exists in v4.2. This is the simplest test I could put together that shows this failure. [Fact]
public void ResolvingFuncWithConstructorArgumentsShouldNotThrow()
{
using (var mock = AutoMock.GetStrict())
{
var testObject = mock.Create<ConcreteWithFuncDependency>();
var result = testObject.Run();
Assert.NotNull(result);
}
}
public interface IFoo
{
}
public class ConcreteWithConstructorArguments
{
private readonly IFoo foo;
public ConcreteWithConstructorArguments(IFoo foo)
{
this.foo = foo;
}
}
public class ConcreteWithFuncDependency
{
private readonly Func<ConcreteWithConstructorArguments> getDependency;
public ConcreteWithFuncDependency(Func<ConcreteWithConstructorArguments> getDependency)
{
this.getDependency = getDependency;
}
public ConcreteWithConstructorArguments Run() => getDependency();
} I can fix the issue by replacing MoqRegistrationHandler.ServiceIsAbstractOrNonSealedOrInterface with the following version: private static bool ServiceIsAbstractOrNonSealedOrInterface(IServiceWithType typedService)
{
var serverTypeInfo = typedService.ServiceType.GetTypeInfo();
return serverTypeInfo.IsInterface
|| serverTypeInfo.IsAbstract
|| (serverTypeInfo.IsClass &&
!serverTypeInfo.IsSealed &&
typedService.ServiceType.GetConstructors().Any(x => !x.GetParameters().Any()));
} With this fix, all tests pass including the test above. I realize that the fix would need to be made a little more robust because it fails for classes that have protected parameterless constructors, and I'm sure a few other scenarios. If this seems like something that should be fixed, I can add tests for edge cases and include the proper binding flags to GetConstructor. Let me know if you want a pull request. Thanks! |
I've hit a similar issue since upgrading to 4.2.0 of this, I have some older code that has concrete dependencies that depend on other concrete dependencies, that is no longer working. This is an example test case that used to work but no longer works on 4.2 due to this issue. using Autofac.Extras.Moq;
using Xunit;
namespace XUnitTestProject1
{
public class UnitTest1
{
[Fact]
public void Test1()
{
using (var env = AutoMock.GetLoose())
{
var sut = env.Create<Sut>();
var result = sut.Test();
Assert.True(result);
}
}
}
public class Sut
{
private readonly Concrete1 _concrete1;
public Sut(Concrete1 concrete1)
{
_concrete1 = concrete1;
}
internal bool Test() => _concrete1.Test1();
}
public class Concrete1
{
private readonly Concrete2 _concrete2;
public Concrete1(Concrete2 concrete2)
{
_concrete2 = concrete2;
}
internal bool Test1() => _concrete2.Test2();
}
public class Concrete2
{
internal bool Test2() => true;
}
} |
With the latest update (4.1.0), tests that worked previously with lazy loaded dependencies are failing with the following error when Lazy types are initialised i.e. *.Value is called.
Controller being tested
Unit Test Example
When upgrading the package this bracks, however when reverting back to 4.0.0 works. Moq version is 4.7.127 for reference.
The text was updated successfully, but these errors were encountered: