Is it possible to assign a fixed value to a property on a child instance when building a parent with Autofixture? It will add default values to all the properties on the child instance like a charm, but I would like to override and assign a specific value to one of the properties on the child instance.
Given this parent/child relationship:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public int Number { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
I would like to assign a specific value to the City property on the address instance. I was thinking in the lines of this test code:
var fixture = new Fixture();
var expectedCity = "foo";
var person = fixture
.Build<Person>()
.With(x => x.Address.City, expectedCity)
.Create();
Assert.AreEqual(expectedCity, person.Address.City);
That is not possible. I guess, by the reflection exception
System.Reflection.TargetException : Object does not match target type.
...that Autofixture tries to assign the value to a City property on the Person instance instead of an Address instance.
Any suggestions?
And yes, I know that I could just add an extra step like the following:
var fixture = new Fixture();
var expectedCity = "foo";
// extra step begin
var address = fixture
.Build<Address>()
.With(x => x.City, expectedCity)
.Create();
// extra step end
var person = fixture
.Build<Person>()
.With(x => x.Address, address)
.Create();
Assert.AreEqual(expectedCity, person.Address.City);
...but was hoping for the first version or something similar (fewer steps, more terse).
Note: I'm using Autofixture v3.22.0
For completeness, here's another way to do it:
fixture.Customize<Address>(c =>
c.With(addr => addr.City, "foo"));
var person = fixture.Create<Person>();
This will customize the creation of all instances of Address
If you end up using this often enough, it may be worthwhile wrapping it inside an ICustomization:
public class AddressConventions : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Address>(c =>
c.With(addr => addr.City, "foo"));
}
}
fixture.Customize(new AddressConventions());
Not to be dismissive of the question, but the simplest solution might actually be this:
[Fact]
public void SimplestThingThatCouldPossiblyWork()
{
var fixture = new Fixture();
var expectedCity = "foo";
var person = fixture.Create<Person>();
person.Address.City = expectedCity;
Assert.Equal(expectedCity, person.Address.City);
}
Assignment of explicit values to properties is something most languages already excel at (C# certainly does), so I don't think AutoFixture needs a complicated DSL to reproduce half of that functionality.
You can use a Do method on the builder:
var person = this.fixture
.Build<Person>()
.Do( x => x.Address.City = expectedCity )
.Create();
You can also inject and freeze your instance to the fixture:
this.fixture.Inject( expectedCity );
Related
I have a class inheriting from another class
I am doing a query from the database
How do I fill in the static List without loop using linq lambda
If he finds a lot of data. this will not be fast
I want to escape from loop
public class Currencys
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long Curr_Id { get; set; }
[StringLength(50)]
public string Curr_Name { get; set; }
[StringLength(50)]
public string CentName { get; set; }
[StringLength(50)]
public string curr_abbrivation { get; set; }
[StringLength(50)]
public string en_curr_name { get; set; }
[StringLength(50)]
public string en_centname { get; set; }
}
public class test1 : Currencys
{
static List<test1> _currenciesList;
public static void Fill()
{
if (_currenciesList != null)
{
_currenciesList.Clear();
}
_currenciesList = new List<test1>();
using (var context = new ContextFormeDb())
{
var list = context.Currencies.ToList();
list.ForEach(o=>
{
test1 _test1 = new test1();
_test1.Curr_Id = o.Curr_Id;
_test1.Curr_Name = o.Curr_Name;
_test1.CentName = o.CentName;
_test1.curr_abbrivation = o.curr_abbrivation;
_test1.en_curr_name = o.en_curr_name;
_test1.en_centname = o.en_centname;
_currenciesList.Add(_test1);
});
}
}
}
Is there anything better than this? without loop
list.ForEach(o=>
{
test1 _test1 = new test1();
_test1.Curr_Id = o.Curr_Id;
_test1.Curr_Name = o.Curr_Name;
_test1.CentName = o.CentName;
_test1.curr_abbrivation = o.curr_abbrivation;
_test1.en_curr_name = o.en_curr_name;
_test1.en_centname = o.en_centname;
_currenciesList.Add(_test1);
});
Is there anything better than this? without loop?
It depends on what you would call better. Faster? Probably not. Not much anyway. Easier to read and understand, easier to test, to debug, to change, to reuse? Probably.
Without Loop? there must be a loop somewhere, but it can be hidden inside a LINQ statement.
Whenever you want to fetch items from a database using entity framework, and you don't want to update the fetched items, always use Select, and select only the properties that you plan to use. Don't fetch the complete items, nor use Include. This will cost you overhead that you will only use if you update the fetched data.
So instead of:
var result = dbContext.Schools
.Where(school => school.Name == "Hogwarts")
.Include(school => school.Students)
.ToList();
consider to use:
var result = dbContext.Schools
.Where(school => school.Name == "Hogwarts")
.Select(school => new
{
// Select only the properties that you plan to use
Id = school.Id,
Name = school.Name,
...
students = dbContext.Students
.Where(student => student.SchoolId == school.Id)
.Select(student => new
{
Id = student.Id,
Name = student.Name,
...
// not needed, you know the value
// SchoolId = student.SchoolId,
})
.ToList(),
})
.ToList();
It will prevent the transfer of properties that you won't use
It will prevent that the fetched data will be copied to DbContext.ChangeTracker.
If you don't put data that won't be changed in the ChangeTracker, then SaveChanges will be faster.
So in your case, your code would be easier to understand, easier to reuse, easier to test and debug, and without "for each" if you use Select:
var fetchedData = dbContext.Currencies
.Where(currency => ...) // if you don't want all currencies
.Select(currency => new
{
// Select only the properties that you plan to use:
Id = currency.Id,
Name = currency.Name,
...
})
.ToList();
I used an anonymous type (new without specifying a class). This way you won't have to create a "dummy" class. The advantage is that you just write the properties and you'll have the object, you even have an "equality by value". If in future you need to add or remove a property, just do it, without any problem, no need to change your dummy class.
Disadvantage: you can't use it outside the current block, and certainly not as a return value of a procedure.
So if you need it outside your procedure:
.Select(currency => new Test1
{
// Select only the properties that you plan to use:
Id = currency.Id,
Name = currency.Name,
...
})
.ToList(),
If two lists are of the same type , you can use AddRange.
if not and for any reason you need to map properties or its diffrent object type, i would suggest configure AutoMapper in your app and like this you can easily convert you List from Type A to Type B and after that use AddRange
I am writing a project that takes a JSON file to deserialize it and Build the data and process them then save it to the database. Now I want to write a unit test using Mock for this class but I don't know how to do this because in this method I only equalize the field in my DTO and database
this is my order Dto
public class OrderDto
{
public int Code { get; set; }
public int CustomerCode { get; set; }
public int StoreCode { get; set; }
public string OrderDate { get; set; }
public string OrderStatus { get; set; }
public string DeliveryDate { get; set; }
}
This is my order builder class
public class OrderBuilder
{
static PracticeEntities _context;
public OrderBuilder(PracticeEntities4 context)
{
_context = context;
}
public static CustomersOrder OrderBuild(OrderDto dto)
{
//using (var context = new PracticeEntities4())
//{
var oldStoreId = _context.Stores.FirstOrDefault(e => e.Code == dto.StoreCode).Id;
var oldCustomerId = _context.Customers.FirstOrDefault(e => e.Code == dto.CustomerCode).Id;
return new CustomersOrder()
{
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
DeliveryDate = Convert.ToDateTime(dto.DeliveryDate),
CustomerId = oldCustomerId,
StoreId = oldStoreId,
Code = dto.Code
};
//};
}
}
UPDATED
First thing to note is that a static class can't be unit tested. So the method to be tested shall be modified as such below shown. Also, the dbcontext i.e. IPracticeEntities4 interface which is implemented in the PracticeEntities4 class need to be injected so that it can be mocked.
public class PracticeEntities4:IPracticeEntities4, DbContext
{
....
}
public class ClassMethod2BTested
{
IPracticeEntities4 _context; //declare the context
public ClassMethod2BTested(IPracticeEntities4 context) // inject the context
{
_context=context; // set the context to local variable
}
public CustomersOrder OrderBuild(OrderDto dto)
{
//using (var context = new PracticeEntities4()) // remove this
{
var oldStoreId = _context.Stores.FirstOrDefault(e => e.Code == dto.StoreCode).Id;
var oldCustomerId = _context.Customers.FirstOrDefault(e => e.Code dto.CustomerCode).Id;
return new CustomersOrder()
{
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
DeliveryDate = Convert.ToDateTime(dto.DeliveryDate),
CustomerId = oldCustomerId,
StoreId = oldStoreId,
Code = dto.Code
};
};
}
}
Now the above method can be united tested.
For unit test, Please check the sample here: Mocking EF DbContext with Moq
Added
Please check this code:
github
Since you are using entity framework, I think this article will help you: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking
Create your own test doubles – This approach involves writing your own in-memory implementation of your context and DbSets. This gives you a lot of control over how the classes behave but can involve writing and owning a reasonable amount of code.
Use a mocking framework to create test doubles – Using a mocking framework (such as Moq) you can have the in-memory implementations of your context and sets created dynamically at runtime for you.
So with the first way you can simulate a db call with specific data and make sure the result returns successfully.
These tests, while not securing business errors protect your code from missing null checks and runtime errors like that.
I have a model which has a generic properties property looking something like this:
public class GenericProperty
{
public string Name { get; set; }
public object Value { get; set; }
}
Next to that I have a object that has a list with GenericProperties like this:
public class GenericEntity
{
public string Name { get; set; }
public List<GenericProperty> Properties { get; set; }
}
Now im calling a API that deserialize the json to the model above. Next i want to use AutoMapper to construct an actual good looking model so i did the following:
Mapper.Initialize(x =>
{
x.CreateMap<GenericEntity, MyModel>()
.ForMember(d => d.ManagerId, o => o.MapFrom(s => s.Properties.Where(n => n.Name == "ManagerId" ).Select(v => v.Value)))
});
Problem is that this returns the property type and not the actual value:
System.Linq.Enumerable+WhereListIterator`1[MyProject.Models.GenericProperty]
How can i lookup the value of within the model?
By using Where you are selecting all the properties with the name ManagerId. You should instead use Single like in this unit test:
public class TestClass
{
[Test]
public void TestMapper()
{
Mapper.Initialize(x =>
{
x.CreateMap<GenericEntity, MyModel>()
.ForMember(d => d.ManagerId,
o => o.MapFrom(s => s.Properties.Single(n => n.Name == "ManagerId").Value));
});
var ge = new GenericEntity
{
Properties = new List<GenericProperty>
{
new GenericProperty {Name = "ManagerId", Value = "Great"}
}
};
var myModel = Mapper.Map<MyModel>(ge);
Assert.AreEqual("Great", myModel.ManagerId);
}
}
If you can not guarantee that there will be a property with the name ManagerId, you should use SingleOrDefault, and handle the null case.
IMHO, you should limit this kind of AutoMapper configurations to simple cases, since it quickly gets difficult to debug and maintain.
For more complex mappings like this one, I would recommend you to make an explicit mapping method instead, which you can call like an extension method. Another option worth considering if you want to use Automapper are Custom value resolvers.
I have implemented a Repository Pattern using an onion Architecture and Entity Framework for Data Access, and now I want to test it using Moq. I just asked a question on SO and with the answer I am now more confused (the answer was good but I have very poor comprehension of how to mock even after reading doc). What I want to do is test Repository method Get(long id). My repository constructor takes a DbContext as parameter(called PrincipalServerContext, so I was suggested to mock the context in order to test my Repository. Let's say this is my Repository:
public class PrincipalServerContext : DbContext
{
public DbSet<Web_Documents> WebDoc { get; set; }
public PrincipalServerContext()
: base("name=PrincipalServerDB")
{
Database.SetInitializer(new Initializer());
}
}
Now one of my POCOs Web_Documents (EF entity):
public class Web_Documents
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IDDocument { get; set; }
[Required]
[MaxLength(255)]
public string NomDocument { get; set; }
[Required]
public long IDCategorie { get; set; }
[ForeignKey("IDCategorie")]
public Web_Categories cat { get; set; }
[Required]
[MaxLength(255)]
public string Lien { get; set; }
[MaxLength(50)]
public string Type { get; set; }
public virtual ICollection<Web_Profils> Profils { get; set; }
}
And finally my Repository method (knowing that repository is generic, I use POCOs as Generic Types):
public T Get(long id)
{
ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext;
ObjectSet<T> set = objContext.CreateObjectSet<T>();
IEnumerable<string> keyNames = set.EntitySet.ElementType
.KeyMembers
.Select(k => k.Name);
if (keyNames.Count() > 1)
return null;
else
{
string idName = keyNames.ElementAt(0); // For Document would be IDDocument
var parameter = Expression.Parameter(typeof(T));
var property = Expression.Property(parameter, idName);
var idValue = Expression.Constant(id, id.GetType());
var equal = Expression.Equal(property, idValue);
var predicate = Expression.Lambda<Func<T, bool>>(equal, parameter);
return entities.SingleOrDefault(predicate);
//Returns the corresponding entity to 'id' and 'T'
}
}
This builds an expression with appropriate ID names because every table has a different ID Name (company's policy).
From what I was told here Should this case of Assert.AreSame return true? I understand that I have to build a return type for the Mock object, but my context class is so thin I don't have any methods or anything, just a DbSet.
So I tried this as a test but it probably makes no sense since it failed (I'm just really lost and don't understand it):
Mock<PrincipalServerContext> moqContext;
public void IdExists(){
moqContext = new Mock<PrincipalServerContext>();
var set = new Mock<DbSet<Web_Documents>>();
moqContext.Setup(c => c.Set<Web_Documents>()).Returns(set.Object);
repoDoc = new Repository<Web_Documents>(moqContext.Object);
var testDoc = repoDoc.Get(1L);
Assert.AreEqual(testDoc.NomDocument, "Ajouter une catégorie");
}
Say I would want to make a simple test to find if the ID searched corresponds to my DB entry, how should I set the moqContext object I am trying to define? In examples I see they usually have methods for their mocked objects, but here none, so I found this Mocking DbContext for TDD Repository which made me try this test.
Thanks for your help!
Here's an example of using the in-memory database.
First you create an request an instance of the mock unit of work.
[TestMethod]
public async Task ExampleTest() {
//arrange
Mock<IUnitOfWork> mockUow = MockUowFactory.Get(nameof(ExampleTest));
//act
using (var app = YOURAPP(mockUow.Object)){
app.METHODUNDERTEST();
}
//assert
...
}
Then you build up the mock unit of work. According to what I've read the separate context is needed (one for seeding, one for testing). The MockEntityFactory just returns an array of dummy data which is used to populate the dbsets in our InMemoryDatabase.
public class MockUowFactory {
public static Mock<IUnitOfWork> Get(string dbName) {
DbContextOptions<YOUR CONTEXT> options = new DbContextOptionsBuilder<YOUR CONTEXT>()
.UseInMemoryDatabase(databaseName: dbName)
.Options;
using (var seedContext = new YOURCONTEXT(options)) {
seedContext.YOURENTITY.AddRange(MockEntityFactory.YOURENTITY);
seedContext.SaveChanges();
}
var context = new YOURCONTEXT(options);
var mockUow = new Mock<IUnitOfWork>();
mockUow.Setup(m => m.Context).Returns(context);
mockUow.Setup(m => m.Save()).Returns(() => context.SaveChanges().ToString());
return mockUow;
}
}
I then pass this unit of work through the necessary layers and don't need to do anything special to test my production code.
Given these two objects
public class UserModel
{
public string Name {get;set;}
public IList<RoleModel> Roles {get;set;}
}
public class UserViewModel
{
public string Name {get;set;}
public IList<RoleViewModel> Roles {get;set;} // notice the ViewModel
}
Is this the most optimal way to do the mapping, or is AutoMapper capable of mapping Roles to Roles on its own?
App Config
Mapper.CreateMap<UserModel, UserViewModel>()
.ForMember(dest => dest.Roles, opt => opt.MapFrom(src => src.Roles));
Mapper.CreateMap<UserViewModel, UserModel>()
.ForMember(dest => dest.Roles, opt => opt.MapFrom(src => src.Roles));
Implementation
_userRepository.Create(Mapper.Map<UserModel>(someUserViewModelWithRolesAttached);
Is this the most optimal way to do the mapping, or is AutoMapper capable of mapping Roles to Roles on its own?
If the property names are identical, you should not have to manually provide a mapping:
Mapper.CreateMap<UserModel, UserViewModel>();
Mapper.CreateMap<UserViewModel, UserModel>();
Just make sure the inner types are mapped as well (RoleViewModel ↔ RoleModel)
What this means, however, is that if you change a source or destination property name, AutoMapper mappings can fail silently and cause hard to track down problems (e.g., if you changed UserModel.Roles to UserModel.RolesCollection without changing UserViewModels.Roles).
AutoMapper provides a Mapper.AssertConfigurationIsValid() method that will check all of your mappings for errors and catch misconfigured mappings. It's useful to have a unit test that runs with the build that validates your mappings for this kind of problem.
You don't need to map the properties. Just make sure that the property names match and there is a mapping defined between them.
Mapper.CreateMap<UserModel, UserViewModel>();
Mapper.CreateMap<UserViewModel, UserModel>();
Mapper.CreateMap<RoleModel, RoleViewModel>();
Mapper.CreateMap<RoleViewModel, RoleModel>();
Or with the cooler way I just found out:
Mapper.CreateMap<UserModel, UserViewModel>().ReverseMap();
Mapper.CreateMap<RoleModel, RoleViewModel>().ReverseMap();
All the other answers, are much better (which I gave an upvote to each).
But what I wanted to post here is a quick playground that you could copy and past right into LinqPad in C# program mode and play your idea's without messing with your actual code.
Another awesome thing about moving all your conversions into a TyperConverter class is that your conversions are now Unit Testable. :)
Here you will notice that the model and viewmodel are almost identical except for one property. But through this process the right property is converted to the correct property in the destination object.
Copy this code into LinqPad and you can run it with the play button after switching to C# Program mode.
void Main()
{
AutoMapper.Mapper.CreateMap<UserModel, UserViewModel>().ConvertUsing(new UserModelToUserViewModelConverter());
AutoMapper.Mapper.AssertConfigurationIsValid();
var userModel = new UserModel
{
DifferentPropertyName = "Batman",
Name = "RockStar",
Roles = new[] {new RoleModel(), new RoleModel() }
};
var userViewModel = AutoMapper.Mapper.Map<UserViewModel>(userModel);
Console.WriteLine(userViewModel.ToString());
}
// Define other methods and classes here
public class UserModel
{
public string Name {get;set;}
public IEnumerable<RoleModel> Roles { get; set; }
public string DifferentPropertyName { get; set; }
}
public class UserViewModel
{
public string Name {get;set;}
public IEnumerable<RoleModel> Roles { get; set; } // notice the ViewModel
public string Thingy { get; set; }
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine(string.Format("Name: {0}", Name));
sb.AppendLine(string.Format("Thingy: {0}", Thingy));
sb.AppendLine(string.Format("Contains #{0} of roles", Roles.Count()));
return sb.ToString();
}
}
public class UserModelToUserViewModelConverter : TypeConverter<UserModel, UserViewModel>
{
protected override UserViewModel ConvertCore(UserModel source)
{
if(source == null)
{
return null;
}
//You can add logic here to deal with nulls, empty strings, empty objects etc
var userViewModel = new UserViewModel
{
Name = source.Name,
Roles = source.Roles,
Thingy = source.DifferentPropertyName
};
return userViewModel;
}
}
public class RoleModel
{
//no content for ease, plus this has it's own mapper in real life
}
Result from the Console.WriteLine(userViewModel.ToString());:
Name: RockStar
Thingy: Batman
Contains #2 of roles
Inside the Startup.cs in the Configure() method:
Mapper.Initialize(config => {
config.CreateMap<UserModel, UserViewModel>().ReverseMap();
// other maps you want to do.
});