Automapper version 12 fails test on MapFrom when using ToLowerInvariant() - entity-framework-core

On Version 11 of automapper the below works fine but now that i upgraded to version 12 it fails. If i remove the ".ToLowerInvariant()" part then it passes the test.
Here is the mapping code:
CreateMap<UserEditProfileViewModel, ApplicationUser>(MemberList.Source)
.ForMember(dest => dest.Email, opts => opts.MapFrom(src => src.Email.ToLowerInvariant()))
.ForMember(dest => dest.UserName, opts => opts.MapFrom(src => src.Email.ToLowerInvariant()))
.ForSourceMember(src => src.Roles, opts => opts.DoNotValidate());
The error message is:
Test method TIP.Tests.TIP.Web.AutoMapperProfiles.AccountManagementProfileShould.BeValid threw exception:
AutoMapper.AutoMapperConfigurationException:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
=======================================================================================================================
UserEditProfileViewModel -> ApplicationUser (Source member list)
TIP.Web.Features.AccountManagement.ViewModels.UserEditProfileViewModel -> TIP.Domain.Entities.Identity.ApplicationUser (Source member list)
Unmapped properties:
Email
Is it a bug or something has changed in version 12? How can i move forward?

Related

NullReferenceException using Where() in AutoMapper.MapFrom

I'm modelling a 3rd party database using Automapper 8 and EF 6.
One of my DTO classes needs to use a Where clause on an association to locate the correct record.
// Community table is mapped and working.
// Mapping breaks when mapping dest.Subjects
cfg.CreateMap<Person, PersonDto>()
// snip many mappings
.ForMember(dest => dest.Id, act => act.MapFrom(src => src.ID))
.ForMember(dest => dest.UserName, act => act.MapFrom(src => src.Community.NetworkLogin))
.ForMember(
dest => dest.Subjects,
act => act.MapFrom(
src => src.Community.StudentClasses.Where(
subject => subject.Year == CurrentSemester.Year && subject.Semester == CurrentSemester.Semester)))
.ForMember(
dest => dest.Contacts,
act => act.MapFrom(
src => src.Community.Contacts.Where(
contact => Contact.UseThis).Select(contact => contact.ContactDetails)));
This code works in production, but I'd really like to Unit Test this model. Running a simple test (get all records in the Mock) I'm hit with a NullReferenceException when it tries to access the Community.StudentClasses object.
I found this answer relating to NullReferenceExceptionexceptions and AutoMapper, which helped me fix the rest of the references in this config, but I'm still having issues with this one. The test works when I remove the Community.StudentClasses mapping.
I'm mocking objects using code similar to:
public static Person Person19788 =>
new SchoolContact
{
ID = 19788,
NetworkLogin = "username",
// Tried various creation methods
// StudentClasses = new List<StudentClass> {new StudentClass()},
// StudentClasses = new List<StudentClass> {new StudentClass {Year = 0, Semester = 0}},
StudentClasses = null,
StudentContacts = null,
Address = Address19788
};
CurrentSemester has been checked, and returns valid non-zero values for Year and Semester.
The strange thing is that the Contacts mapping works fine, even with null values. So I assume that I've broken my Subjects mapping somewhere along the line, but I'm unsure where else to look.
It turns out that the problem was with my Subjects mapping after all.
The top-level associations were mapped correctly, however the lower-level associations were not. (I didn't include these mappings because a) I didn't think about them, and b) there's only so much code that anyone would be willing to wade through).
After fixing up the w > x > y > z mappings everything is working as expected. I thought I'd exhausted all options before posting this question. Lesson learned: don't post to SO until you've slept on it and taken a fresh look at the code the next day.

parse.form method defined in play framework 2.2.x?

Play documentation mentions parse.form method which can be used to bind to an incoming request. I am using play 2.2.x. Is this method defined in this release? I am getting compilation error
value form is not a member of object controllers.Application.parse
def regSubmit = Action(parse.form(userForm) { implicit request =>
val userData= request.body
Ok(views.html.regconf("Registration Successful")(userForm.fill(userData)))
})
As far as I can tell from the 2.2.x source code, parse.form did not exist then, and was only introduced in 2.4.x.
Any reason not to use the "equivalent" bindFromRequest and deal with errors that might be present? Along the lines of:
def regSubmit = Action { implicit request =>
userForm.bindFromRequest.fold (
errors => //-- 'errors' is a form with FormErrors set
Ok(views.html.register(errors)) //-- register is the initial form
userData => //-- 'userData' is the case class that userForm maps to
Ok(views.html.regconf("Registration Successful")(userForm.fill(userData)))
)
}
I have not checked the source code to see whether it is in 2.2.x. It is not mentioned on the ScalaForms page of the docs.

FluentAssertions graph comparison, ExcludingNestedObjects ignored?

I've got a unit/integration test as follows.
using (var repository = _factory.Get())
{
applicationBefore = repository.Applications
.Include(a => a.AcceptedAgreements)
.Single(a => a.AggregateId == applicationId);
}
// Perform an operation that deletes an Application and all
// related data and then rebuilds it from the event store.
Repo.Application applicationAfter = null;
using (var repository = _factory.Get())
{
applicationAfter = repository.Applications
.Include(a => a.AcceptedAgreements)
.Single(a => a.AggregateId == applicationId);
}
applicationAfter.AcceptedAgreements.ShouldAllBeEquivalentTo(applicationBefore.AcceptedAgreements, options => options
.ExcludingNestedObjects());
The repository reference is a DbContext and AcceptedAgreements is a navigation property.
This test fails with the following message.
Result Message:
FluentAssertions.Execution.AssertionFailedException :
Expected item[0].Application.Id to be 1, but found 2.
<more failures where stuff inside Application is different>
With configuration:
- Use declared types and members
- Compare enums by value
- Include all non-private properties
- Include all non-private fields
- Match member by name (or throw)
- Be strict about the order of items in byte arrays
- FluentAssertions.Equivalency.ShouldAllBeEquivalentToHelper+CollectionMemberOrderingRuleDecorator
If I modify the assertion as follows:
applicationAfter.AcceptedAgreements.ShouldAllBeEquivalentTo(applicationBefore.AcceptedAgreements, options => options
.Excluding(o => o.Application));
Now the test passes.
Please help me understand why ExcludingNestedObjects() doesn't exclude the Application property, which is in fact a nested object, and I have to resort to excluding each navigation property individually. The above code is slightly simplified as I actually have multiple navigation properties and have to exclude each of them individually.

EF6 error when using in-memory testing

Mocked setup below (the GenerateTrades() and other methods in ContextFactory are just returning a List AsQueryable with sample data):
_trades = ContextFactory.GenerateTrades();
_hedges = ContextFactory.GenerateHedges();
_exposures = ContextFactory.GenerateExposures();
_ctx = new Mock<FxContext>();
var fakeTrades = new Mock<DbSet<Trade>>();
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Provider).Returns(_trades.Provider);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Expression).Returns(_trades.Expression);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.ElementType).Returns(_trades.ElementType);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.GetEnumerator()).Returns(_trades.GetEnumerator());
var fakeHedges = new Mock<DbSet<Hedge>>();
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Provider).Returns(_hedges.Provider);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Expression).Returns(_hedges.Expression);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.ElementType).Returns(_hedges.ElementType);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.GetEnumerator()).Returns(_hedges.GetEnumerator());
var fakeExposures = new Mock<DbSet<Exposure>>();
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Provider).Returns(_exposures.Provider);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Expression).Returns(_exposures.Expression);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.ElementType).Returns(_exposures.ElementType);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.GetEnumerator()).Returns(_exposures.GetEnumerator());
_ctx.Setup(c => c.Trades).Returns(fakeTrades.Object);
_ctx.Setup(c => c.Hedges).Returns(fakeHedges.Object);
_ctx.Setup(c => c.Exposures).Returns(fakeExposures.Object);
Part of test code looks like:
_sut = (from x in _ctx.Object.Hedges
where x.Id == ContextFactory.s_hedge01Id
select x).FirstOrDefault();
_ctx.Object.Hedges.Attach(_sut);
_ctx.Object.Entry(_sut).Collection(x => x.HedgedTrades).Load();
On the last line I get an exception:
{"Member 'Load' cannot be called for property 'HedgedTrades' because the entity of type 'Hedge' does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Hedge>."}
I have verified that in fact the _sut Hedge is actually an instance of a Hedge (not null or a stub) and as the code seems to indicate, I have attached the Hedge to the context explicitly (though I would think the query should bring the object into the context automagically). Am I missing something?
It seems like here in your test you are mixing two separate approaches. Error you received states that you are trying to access DbContext inherited logic, but it is mocked. If you want to perform your unit tests against database with use of FxContext then do not mock it. If you want test other part of software then you should mock interface that FxContext should implement. This will enable you to fullfil dependency injection principle in your code which will help you then organize your test in more predictable way.

How do I setup Autofac such that it can pass a registered component as an argument to another component?

I have
builder.Register<ISomething>(c => new Something()).InstancePerLifetimeScope();
what would this look like in Autofac if Something took an argument that was an interface also resolved by Autofac?
builder.Register<ISomeInitializer>(c => new SomeInitializer()).InstancePerLifetimeScope();
builder.Register<ISomething>(c => new Something(????)).InstancePerLifetimeScope();
If you don't want to pass any special argument to your services then you can just write:
builder.Register<SomeInitializer>().As<ISomeInitializer>()
.InstancePerLifetimeScope();
builder.Register<Something>().As<ISomething>()
.InstancePerLifetimeScope();
In this case Autofac will instantiate your SomeInitializer with its default constructor and it will instantiate your Something with passing in the SomeInitializer.
In you want to keep your current code you can use the c parameter (which is an IComponentContext) to resolve your dependencies:
builder.Register<ISomeInitializer>(c => new SomeInitializer())
.InstancePerLifetimeScope();
builder.Register<ISomething>(c => new Something(c.Resolve<ISomeInitializer>()))
.InstancePerLifetimeScope();