question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AutoNSubstitute gives AutoFixture.ObjectCreationException when trying to Build then Create

See original GitHub issue

I’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:closed
  • Created a year ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
GeraldLxcommented, Jul 26, 2022

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:

var entity = fixture.Create<IEntity>();

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:

var entity = fixture.Build<IEntity>()
  .FromFactory(() => Substitute.For<IEntity>())
  .With(e => e.Code, "0")
  .Create();

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:

var entity = fixture.Create<IEntity>();
entity.Code = 0;

or

var entity = fixture.Create<IEntity>();
entity.Code.Returns(0);

for readonly properties.

Then you can use the customization and let AutoFixture create the substitutes. Any unwanted randomization you just overwrite.

0reactions
bkqccommented, Jul 26, 2022

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 the Returns(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?

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found