Replies: 10 comments 7 replies
-
@bkqc can you provide a minimum reproducible example? |
Beta Was this translation helpful? Give feedback.
-
I have no clue what you were changing, but it must be something more than just upgrading the version of AutoFixture. The problem is the class SelectList from the Microsoft.AspNet.Mvc package. I made a .NET Framework console app and added the following NuGet packages: When I run the following code:
I get the same error you posted, but a downgrade to AutoFixture 3.51.0 changes nothing. Still the same error. If you look at the source for the class, you can easily spot the problem:
The class has a ctor taking an IEnumerable. There is no type supplied, so basically the constructor takes anything that can be iterated over. So you must help AutoFixture to supply a solution for this. I am quite sure that your old code had some kind of customization that has been lost in the upgrade process. |
Beta Was this translation helpful? Give feedback.
-
Trying to create the smallest solution possible having the problem, I think I found where the problem is coming from but not why.
With or without the cast, it works in 3.51 but crashed in 4.0.0 and 4.18 on
The project is attached here. Note that the implementation projet is in 4.5.2 and the test project, 4.8 though I don't think it has an any influence. |
Beta Was this translation helpful? Give feedback.
-
I looked up your code. Sadly I am not using AutoFixture long enough to explain, why it worked in the old version. But the good news is, that there is an easy fix. First of all you have the problem with the SelectList as I have posted before. You are not creating a SelectList explicitly, but one of your classes has this type as a property with a setter. So AutoFixture will normally create it.
can be simplified to
But that does not solve the problem. The main problem is this:
Basically Build and Customize are for the same thing. Customize changes the way for every ListeCommunicationModel that will be created by the fixture, while Build allows you to create a special version of the type. Basically it is a one time customization. Sadly customizations dont add up. (Maybe this was the case in older versions?) So your code basically changes the way AutoFixture handles creating ListeCommunicationModel. But then you say, but for this instance build it the default way. So you can either delete the customization code and add the With/Without statement to the Build chain:
Or keep the customization and just create the instance by:
|
Beta Was this translation helpful? Give feedback.
-
I started to read the Changelog for v4. Seems a little tragic for you. I could not find anything explaining the changed behavior in the breaking changes list. The reason it works in the old AutoFixture version was a bug. As I explained before. Customize changes the way Create works. If you start with Build, you ignore what Customize did. If you check here: You can find So basically your tests seem to rely on this bug. It is hard to give good advices, if I dont know the problems. If all your problems are just related to SelectList, you could solve this by a customization for this type. |
Beta Was this translation helpful? Give feedback.
-
I dont get your Without question. Considering that you compile your projects with enabled Nullable, then there is nothing special about AutoFixture. Considering a class like this:
You can create it with AutoFixture e.g.:
And of course you will get a warning about the null value for Body. After all it is declared as non nullable. But this has nothing to do with AutoFixture.
will do exaclty the same as the AutoFixture code and produce exactly the same warning. Without is just a way to tell AutoFixture to completly ignore the property. So noting is special about nullable properties. (The confusing part about developers exploring the nullable reference type feature is, that this is just a C# feature. You are basically telling the compiler, that you dont want null values for this property. Therefore you get warnings, if you do so. But technically reference types can always be null. Therefore you can set them to null. The ! just tells the compiler to shut up and suppress the warning) |
Beta Was this translation helpful? Give feedback.
-
@bkqc as @Ergamon mentioned the behavior you used to rely on was a bug, which was fixed back in 2017. The same syntax you used to apply will not work in latest version. You can see the reason begin the fix in the PR #781. As far as I can tell the reason was the necessity to isolate composition graphs for polymorphic types, as well as tests that needed to customize the same type multiple times (override previous customization). Not sure if this will help, but a while back I put together this custom implementation for reusing post-processing expressions. It should allow you to encapsulate what you previously had inside the public class ModelWithoutSortingProperties : IPartialPostprocessComposer<ListeCommunicationModel>
{
public IPostprocessComposer<ListeCommunicationModel> Compose(IPostprocessComposer<ListeCommunicationModel> composer)
{
return composer.Without(y => y.SortingProperties);
}
}
[TestMethod]
public void Foo()
{
_ = _fixture.Build<ListeCommunicationModel>()
.Using(new ModelWithoutSortingProperties())
.With(x => x.SomeOtherProperty, "Some value")
.Create();
} You're still going to have update your entire test suite, but these changes should be less invasive.
|
Beta Was this translation helpful? Give feedback.
-
So I used an implementation similar to what @aivascu suggested and it works fine for objects that are superficially customized but what if I want to have every instance of a given nested type created a specific way but some properties of a superficial one specfici to a given test? For instance
From what I understand right now of the new behaviour, I would have to add With clauses to CreateMany Type2 which would call Build with another With to Build Type3 and repeat the process for Type4 and every nested instance of the Type3 array and so on if I got it nested elsewhere or worse, deeper. This looks like a lot of work for something that used to be simple. Isn't there a way to scope a sub fixture from a parent one for instance or tell Build to import parent Customization maybe? |
Beta Was this translation helpful? Give feedback.
-
@bkqc well the Assuming a type structure similar to one that you've shown above, your type customization would look something like below. [Fact]
public void Foo()
{
var fixture = new Fixture();
fixture.Customize<TypeA>(c => c
.With(x => x.Prop1, "Custom Prop 1")
.With(x => x.PropB, (IFixture f) => f.Build<TypeB>()
.With(y => y.PropC1, (IFixture f) => f.Build<TypeC>()
.With(z => z.Prop1, "Type C Value 1")
.Create())
.CreateMany().ToArray())
.With(x => x.PropD, (IFixture f) => f.Build<TypeD>()
.With(y => y.PropC2, (IFixture f) => f.Build<TypeC>()
.With(z => z.Prop1, "Type C Value 2")
.CreateMany().ToArray())
.Create()));
var data = fixture.CreateMany<TypeA>();
Assert.All(data, item =>
{
Assert.Equal("Custom Prop 1", item.Prop1);
Assert.All(item.PropB, item2 => Assert.Equal("Type C Value 1", item2.PropC1.Prop1));
Assert.All(item.PropD.PropC2, item3 => Assert.Equal("Type C Value 2", item3.Prop1));
});
} Is this lengthier? Probably, yes. Either way this behavior won't change back since it would re-introduce the problems from v3. We are trying to maintain backward compatibility as much as possible, but there are breaking changes and there will be more in the following major versions. |
Beta Was this translation helpful? Give feedback.
-
Then maybe adding a new method to the |
Beta Was this translation helpful? Give feedback.
-
Hi,
I know I'm late to the party but you know how so companies may be slow to move the boat...
I actually have all my tests are configured to use AutoFixture v3.51 and are working as expected.
To be able to use new features from AF and helpers NuGets, we want to move forward in our versions so I first moved to 4.2.1 I started to get
AutoFixture.ObjectCreationExceptionWithPath: AutoFixture was unable to create an instance from System.Collections.IEnumerable because it's an interface.
errors so I moved back to 3.5.1 to make sure and everything passed again. I then tried to upgrade to the right next available version: 4.0.0 but got the same error.
I read the Release Notes 3 times about 4.0.0 but can't find anything that seems to explain the problem I'm facing.
How can I know which constructor argument or property is the problem? Why was it working in 3.5.1?
The complete error was
Thank you :)
Beta Was this translation helpful? Give feedback.
All reactions