AutoNSubstitute gives AutoFixture.ObjectCreationException when trying to Build then Create
See original GitHub issueI’m trying to create a mock object using AutoNSubstitute but I keep getting the following error:
AutoFixture.ObjectCreationException:
Message=The decorated ISpecimenBuilder could not create a specimen based on the request: MySpace.IEntity. This can happen if the request represents an interface or abstract class; if this is the case, register an ISpecimenBuilder that can create specimens based on the request. If this happens in a strongly typed Build<T> expression, try supplying a factory using one of the IFactoryComposer<T> methods.
The stripped down code I use that crashes is
IFixture _fixture = new Fixture().Customize(new AutoNSubstituteCustomization() { ConfigureMembers = true });
var mock = _fixture.Build<IEntity>().Create();
The target is
var mockCol = _fixture.Build<IEntity>().With(e => e.Code, "0").CreateMany();
I also tried these that do work with the last 2 having their properties correctly filled by AutoFixture
var test1 = _fixture.Build<IEntity>();
var test2 = _fixture.Build<IEntity>().With(e => e.Code, "0");
var test3 = _fixture.Create<IEntity>();
var test4 = _fixture.CreateMany<IEntity>();
Stack of the exception
at AutoFixture.Kernel.NoSpecimenOutputGuard.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.FilteringSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Dsl.NodeComposer`1.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
at AutoFixture.Dsl.CompositeNodeComposer`1.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.SpecimenContext.Resolve(Object request)
at AutoFixture.Kernel.SeedIgnoringRelay.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.FilteringSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Dsl.NodeComposer`1.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
at AutoFixture.Dsl.CompositeNodeComposer`1.Create(Object request, ISpecimenContext context)
at AutoFixture.Kernel.SpecimenContext.Resolve(Object request)
at AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context)
at AutoFixture.SpecimenFactory.Create[T](ISpecimenBuilder builder)
at AutoFixture.SpecimenFactory.Create[T](IPostprocessComposer`1 composer)
at MySpace.Tests.MyTest()
I have also opened a question on StackOverflow with the exact same detail, just in case.
Issue Analytics
- State:
- Created a year ago
- Comments:6 (1 by maintainers)
Top Results From Across the Web
AutoFixture Discussions!
Explore the GitHub Discussions forum for AutoFixture AutoFixture. Discuss code, ask questions ... ObjectCreationException when trying to Build then Create.
Read more >AutoFixture.ObjectCreationException when create a list
I am trying to mock data for particular method using AutoFixture . _dataProvider = Substitute.For<IEstimationDataProvider>(); var rateTypes = ...
Read more >Create and Build
Create and Build. AutoFixture gives its users the ability to quickly create anonymous variables or to customize how they are created, totally or...
Read more >Class NSubstituteBuilder | AutoFixture
Gets a specification that determines whether a substitute should be created for a given request. Declaration. public IRequestSpecification ...
Read more >Customizations with AutoFixture
AutoFixture would throw an exception at you. AutoFixture is not able to create an instance of this interface without a constructor. So you...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I tried to explain it in my initial post here, but I can try again 😉
AutoFixture can create certain types out of the box, like strings etc. What AutoFixture cannot create is e.g. an abstract class or an interface.
When you request a type from AutoFixture, AutoFixture checks internally which part of the configuration can create the type.
So when you add the AutoNSubstitute configuration, you basically extend the AutoFixture configuration to make the creation of abstract classes and interfaces possible.
So with the customization in place, you can successfully run this code:
This gives a fully created entity with all members set.
What you tried to achieve was building an object with AutoFixture. When you do this, you do not use any customizations. You start from scratch generating a new object. Therefore with or without the customization AutoFixture has no clue how to build an IEntity instance. You can add the creation logic by using the FromFactory method. This method has a few overloads.
So the simplest approach for your problem could be:
Another overload takes a specimen builder instance. So instead of calling Substitute.For myself, my code used the component from the customization library. In simple cases both code snippets lead to the same result.
But as @aivascu already said, the simple solution only works for properties with setters. The SubstituteRelay also gives random values to readonly properties.
The same goes for the With statement. You cannot use it for readonly properties, cause sadly this is hard coded in AutoFixture. There is no way to tell AutoFixture “hey, I have a customization that can do that”.
So unless you dont want to go very deep into AutoFixture and dont have the need to make your tests free of NSubstitute referenes, I would advice to write your tests more like this:
or
for readonly properties.
Then you can use the customization and let AutoFixture create the substitutes. Any unwanted randomization you just overwrite.
Wow, thanks @GeraldLx! This is an awesome explanation. Thank you so much! Something like this should go into the official documentation to help understand the Build behaviour!
However, I don’t understand the part where you say that using your last snippets would prevent from having NSubstitute references in my tests. AutoNSubstitute needs a reference to NSubstitute (though it is not shown if using PackageReference but I would also not have control on the version used) and
Using NSubstitute
is, AFAIK, needed to use theReturns(0)
extension method. And in that case, it would look like I could still use my proposed solution. So I take it that your final point is to try to keep only one mocking language inside a given test code project, right?