I have a class
public class Restrictions
{
[Key]
public short RestrictionId { get; set; }
public string Description { get; set; }
public string BlockCode { get; set; }
public List<CustomerRestrictions> CustomerRestrictions { get; set; }
}
And
public class CustomerRestrictions
{
public int CustomerId { get; set; }
public CustomerContacts CustomerContacts { get; set; }
public string RestrictionId { get; set; }
public Restrictions Restrictions { get; set; }
}
Then
public class CustomerContacts
{
[Key]
public long CustomerId { get; set; }
public string Btn { get; set; }
public List<CustomerRestrictions> CustomerRestrictions { get; set; }
}
It seems to be many-to-many relationship.
Now I want to do a unit test for the controller. There is a similar example.
But it doesn't have many to many.
My controller is
[Route("api/[controller]")]
public class BtnRulesController : Controller
{
private readonly IBtnRulesRepository _btnRulesRepository;
public BtnRulesController(IBtnRulesRepository btnRulesRepository)
{
_btnRulesRepository = btnRulesRepository;
}
// GET api/BtnRules
[HttpGet]
public IList<Restrictions> Get()
{
return _btnRulesRepository.GetRestrictions();
}
The difficult thing is how to create sample data in unit test at this moment.
public class SimpleBtnRulesControllerTest
{
[Fact]
public void GetAllBtnRules_Should_Return_All_BtnRules()
{
var repo = new Mock<IBtnRulesRepository>().Object;
var controller = new BtnRulesController(repo);
var testBtnRules = GetTestBtnRules();
var result = controller.Get();
Assert.Equal(testBtnRules.Count,result.Count);
}
public List<Restrictions> GetTestBtnRules()
{
var testBtnRules = new List<Restrictions>();
var testCustomerRestrictionsList = new List<CustomerRestrictions>();
var testCustomerRestrictions = new CustomerRestrictions();
testCustomerRestrictions.CustomerId = 1;
testCustomerRestrictions.RestrictionId = "1";
testCustomerRestrictions.Restrictions=new Restrictions();
testCustomerRestrictions.CustomerContacts=new CustomerContacts();
testCustomerRestrictionsList.Add(new CustomerRestrictions());
testBtnRules.Add(new Restrictions() {RestrictionId = 1, Description = "Demo1",BlockCode = "AdminBlock1",testCustomerRestrictionsList});
testBtnRules.Add(new Restrictions() { RestrictionId = 2, Description = "Demo2", BlockCode = "AdminBlock2" ,testCustomerRestrictionsList});
return testBtnRules;
}
However I get the error CS0747 Invalid initializer member declarator.
There are two things incorrect with your code that I can see.
Firstly, when you are setting the testCustomerRestrictionsList you do not name the Property that it is being assigned to and this is the compiler error.
Your code should look like:
testBtnRules.Add(new Restrictions() {RestrictionId = 1, Description = "Demo1",BlockCode = "AdminBlock1", CustomerRestrictions = testCustomerRestrictionsList});
In this case I wouldn't worry too much about hardcoding the Restrictions into your unit test. But in the future you may want to look into something like AutoFixture so that you don't need to worry so much about creating your objects.
Secondly, you are not setting up the call to the mock IBtnRulesRepository when the GetRestrictions method is called.
Your test should look like:
[Fact]
public void GetAllBtnRules_Should_Return_All_BtnRules()
{
var repo = new Mock<IBtnRulesRepository>();
var testBtnRules = GetTestBtnRules();
repo.Setup(mock => mock.GetRestrictions())
.Returns(testBtnRules)
.Verifiable();
var controller = new BtnRulesController(repo.Object);
var result = controller.Get();
Assert.Equal(testBtnRules.Count,result.Count);
repo.Verify();
}
Related
My question is simple.
I am working with a testcase given to me in C#.
In this test case they have a Parent class containing all the methods and subclasses that will call those methods.
So as far as I know. You can do that by:
Class object = new Class(arguments);
Then call the parent methods like this object.Method()
Now the test I am working with has it written like this: Class.Method()
So just to make my question more clear here is an example of what they have:
Book harryPotterBook = new Book { title = "Harry Potter" };
var savedBook = Book.Find(harryPotterBook.Id);
and here is what I understand it should be:
var savedBook = harryPotterBook.Find(harryPotterBook.Id);
So is this possible? I just want to know what I am missing here.
Thank you.
I'm not sure I understand what you're trying to do right now, because in your example, you seem to be asking how to generate a class with a constructor. If you want to create a class constructor you have to write it like this:
public class Class
{
string name;
public Class(string pName)
{
name = pName;
}
}
Otherwise, if you know that this class is going to be used often as a standard. You can use interfaces:
interface IBasicClass
{
string name { get; set; }
string description { get; set; }
int numberOfPage { get; set; }
int currentPage { get; set; }
void NextPage();
void PreviousPage();
}
public class BasicClass : IBasicClass
{
public string name { get; set; }
public string description { get; set; }
public int numberOfPage { get; set; }
public int currentPage { get; set; }
//Default Constructor
public BasicClass()
{
name = "";
description = "";
numberOfPage = 0;
currentPage = 0;
}
//Constructor
public BasicClass(string pName, string pDescription, int pNumberOfPage)
{
name = pName;
description = pDescription;
numberOfPage = pNumberOfPage;
}
public void PreviousPage()
{
--currentPage;
}
public void NextPage()
{
++currentPage;
}
}
public class Class : MonoBehaviour
{
BasicClass _basicClass;
BasicClass _basicClass2;
void Start()
{
_basicClass = new BasicClass();
_basicClass2 = new BasicClass("Books", "It's a good book", 1);
}
void Update()
{
_basicClass.NextPage();
_basicClass2.NextPage();
}
}
I have just started using AutoMapper on an asp net core project and I'm trying to map an object that has a collection of an object that also has a collection of an object to an entity.
The source
public class MyClass
{
public List<MyCollection> MyCollections { get; set; }
}
public class MyCollection
{
public int CollectionId { get; set; }
public List<Description> Descriptions { get; set; }
}
public class Description
{
public int DescriptionId { get; set; }
public string Text { get; set; }
}
The destination
public class DescriptionToCollection
{
public int DescriptionId { get; set; }
public int CollectionId { get; set; }
}
I've played around with ConvertUsing thinking something like this, but I can't make it work.
CreateMap<MyClass, List<DescriptionToCollection>>()
.ConvertUsing(source => source.MyCollections.Select(x =>x.Description.Select(y=> new DescriptionToCollection{ DescriptionId=y.DescriptionId,CollectionId=x.CollectionId}).ToList()
));
Searching AutoMappers docs and the internet, I couldn't find anything similar to my problem.
Any help is highly appreciated.
Besides a typo in your example code, you almost had it. Because you aren't mapping 1:1 at the top level, you need to flatten somewhere, and you do that using SelectMany, moving the ToList call appropriately.
CreateMap<MyClass, List<DescriptionToCollection>>()
.ConvertUsing(source => source.MyCollections.SelectMany(x => // SelectMany to flatten
x.Descriptions.Select(y =>
new DescriptionToCollection
{
DescriptionId = y.DescriptionId,
CollectionId = x.CollectionId
}
) // ToList used to be here
).ToList()
);
Try to implement ITypeConverter, follow the example code:
Your Classes
public class Class1
{
public List<Class2> class2 { get; set; }
}
public class Class2
{
public int CollectionId { get; set; }
public List<Class3> class3 { get; set; }
}
public class Class3
{
public int DescriptionId { get; set; }
public string Text { get; set; }
}
public class ClassDto
{
public int DescriptionId { get; set; }
public int CollectionId { get; set; }
}
The custom map
public class ClassCustomMap : ITypeConverter<Class1, List<ClassDto>>
{
public List<ClassDto> Convert(Class1 source, List<ClassDto> destination, ResolutionContext context)
{
var classDtoList = new List<ClassDto>();
foreach (var item in source.class2)
{
var collectionID = item.CollectionId;
foreach (var obj in item.class3)
{
var classDto = new ClassDto();
classDto.CollectionId = collectionID;
classDto.DescriptionId = obj.DescriptionId;
classDtoList.Add(classDto);
}
}
return classDtoList;
}
}
The mapping declaration
CreateMap<Class1, List<ClassDto>>().ConvertUsing<ClassCustomMap>();
How to use it
var class2 = new Class2();
class2.CollectionId = 2;
var class3 = new Class3();
class3.DescriptionId = 1;
class3.Text = "test";
class2.class3 = new System.Collections.Generic.List<Class3>() { class3 };
var class1 = new Class1();
class1.class2 = new System.Collections.Generic.List<Class2>() { class2 };
var result = mapper.Map<List<ClassDto>>(class1);
For clarity and to simplify I have used explicit cycles, if you want you can optimize the conversion function using LinQ and Lambda
You are missing the purpose of auto-mapper.
It should be used for transforming an input object of one type into an output object of a different type.
And you wanted to create a map from MyClass type to List - this should be treated as projection.
You can achieve that using LINQ (for example as a extension method on MyClass):
public static class MyClassExtension
{
public static List<DescriptionToCollection> ToDescriptionToCollection(this MyClass value)
{
return value.MyCollections.SelectMany(mc => mc.Descriptions.Select(d => new DescriptionToCollection()
{
CollectionId = mc.CollectionId,
DescriptionId = d.DescriptionId
})).ToList();
}
}
I want to Find Username by userId
this code snippet working
Discussion_CreateBy = db.AspNetUsers.Find(discussion.CreatedBy).UserName,
and this once not working in following controller class
Comment_CreateBy = db.AspNetUsers.Find(c.CreatedBy).UserName,
this is my model classes
public class DiscussionVM
{
public int Disussion_ID { get; set; }
public string Discussion_Title { get; set; }
public string Discussion_Description { get; set; }
public Nullable<System.DateTime> Discussion_CreateDate { get; set; }
public string Discussion_CreateBy { get; set; }
public string Comment_User { get; set; }
public IEnumerable<CommentVM> Comments { get; set; }
}
public class CommentVM
{
public int Comment_ID { get; set; }
public Nullable<System.DateTime> Comment_CreateDate { get; set; }
public string Comment_CreateBy { get; set; }
public string Comment_Description { get; set; }
}
this is whole controller class
public ActionResult Discussion_Preview()
{
int Discussion_ID = 1;
var discussion = db.AB_Discussion.Where(d => d.Discussion_ID == Discussion_ID).FirstOrDefault();
var comments = db.AB_DiscussionComments.Where(c => c.Discussion_ID == Discussion_ID);
DiscussionVM model = new DiscussionVM()
{
Disussion_ID = discussion.Discussion_ID,
Discussion_Title = discussion.Discussion_Name,
Discussion_Description = discussion.Discussion_Name,
Discussion_CreateBy = db.AspNetUsers.Find(discussion.CreatedBy).UserName,
Discussion_CreateDate = discussion.CreatedDate,
Comments = comments.Select(c => new CommentVM()
{
Comment_ID = c.Comment_ID,
Comment_Description = c.Comment_Discription,
Comment_CreateBy = db.AspNetUsers.Find(c.CreatedBy).UserName,
Comment_CreateDate = c.CreatedDate
})
};
return View(model);
}
Getting following error
Method 'Project.Models.AspNetUser Find(System.Object[])' declared on type 'System.Data.Entity.DbSet1[Project.Models.AspNetUser]' cannot be called with instance of type 'System.Data.Entity.Core.Objects.ObjectQuery1[Project.Models.AspNetUser]'
Discussion_CreateBy = db.AspNetUsers.Find(discussion.CreatedBy).UserName
Works because discussion is an in-memory object because you are executing a query by calling FirstOrDefault on it:
var discussion = db.AB_Discussion.Where(d => d.Discussion_ID == Discussion_ID).FirstOrDefault();
On the other hand in the following statement:
db.AspNetUsers.Find(c.CreatedBy).UserName
c is not queried yet because
db.AB_DiscussionComments.Where(c => c.Discussion_ID == Discussion_ID)
returns an IQueriable and not the actual collection of comments
The easiest way to fix it is to bring all your comments into memory (since you are anyway need them all) :
var comments = db.AB_DiscussionComments.Where(c => c.Discussion_ID == Discussion_ID).ToList();
I create an new Contractor object "gc" that calls a method GetContractor() to return all the properties. The results it is returning is correct, however the "gc" object shows all "NULL". I assume I doing something incorrectly in my aspx.cs page?
aspx.cs
protected void fvWasteCollected_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName.Equals("Insert")){
ValidationSummaryWasteDetail.ValidationGroup = "WasteReceivedDetail";
if (IsValid) {
odsMRWWasteCollectedDetail.InsertParameters["WasteTypeId"].DefaultValue = ddlWasteCollectedType.SelectedValue;
odsMRWWasteCollectedDetail.InsertParameters["DisposalMethodId"].DefaultValue = ddl_disposalMethod.SelectedValue;
Contractor gc = new Contractor();
gc.GetContractor(2);
var contractorName = gc.MRWContractorName;
}
}
}
.cs
public class Contractor
{
public Contractor GetContractor(int MRWContractorId)
{
using (DataAccessLINQDataContext db = new DataAccessLINQDataContext())
{
var result = db.MRWContractors.Where(c => c.MRWContractorId == MRWContractorId).Select(c => new Contractor
{
MRWContractorId = c.MRWContractorId,
MRWContractorName = c.MRWContractorName,
MRWContractorAddress = c.MRWContractorAddress,
MRWContractorCity = c.MRWContractorCity,
MRWContractorStateCode = c.MRWContractorStateCode,
MRWContractorZipCode = c.MRWContractorZipCode,
MRWContractorPhone = c.MRWContractorPhone,
MRWContractorFax = c.MRWContractorFax,
MRWContractorEmail = c.MRWContractorEmail
}).SingleOrDefault();
return result;
}
}
public int MRWContractorId { get; set; }
public string MRWContractorName { get; set; }
public string MRWContractorAddress { get; set; }
public string MRWContractorCity { get; set; }
public string MRWContractorStateCode { get; set; }
public int? MRWContractorZipCode { get; set; }
public string MRWContractorPhone { get; set; }
public string MRWContractorFax { get; set; }
public string MRWContractorEmail { get; set; }
}
You are loosing the value of gc when you dont assign it to something.
Try this instead:
var contractor = gc.GetContractor(2);
var contractorName = contractor.MRWContractorName;
You are creating one empty instance of the object that is only used to call the GetContractor method. The GetContractor method creates another instance that contains data, which is returned, but you just throw that instance away and expect the data to be available in the first instance that never got populated.
Make the GetContractor method static so that you don't need an instance to call it:
public static Contractor GetContractor(int MRWContractorId)
Now you can call the method to get that instance that contains the data, without first creating an empty instance:
Contractor gc = Contractor.GetContractor(2);
string contractorName = gc.MRWContractorName;
Say I have this simple entity:
public class Person
{
public int PersonID { get; set; }
public string Name { get; set; }
}
The entity framework can infer by convention that the PersonID field is the primary key. However, if I give the model builder this class:
public class PersonCfg : EntityTypeConfiguration<Person>
{
public PersonCfg()
{
ToTable("Person", "Person");
HasKey(p => p.PersonID);
}
}
Would that improve startup performance? My thought was it might allow EF to do less reflecting and startup the app faster but I don't know how it works behind the scenes to know if it has any impact.
To test this, you can use the DbModelBuilder class to build the model yourself and track the speed of the "Compile" step.
Here's my example code (LinqPad script):
void Main()
{
// Initialize the overall system, but don't count the result.
BuildC();
DateTime startDateA = DateTime.Now;
BuildA();
DateTime.Now.Subtract(startDateA).TotalMilliseconds.Dump("A");
DateTime startDateB = DateTime.Now;
BuildB();
DateTime.Now.Subtract(startDateB).TotalMilliseconds.Dump("B");
}
public class PersonA
{
public int PersonAId { get; set; }
public string Name { get; set; }
}
private void BuildA()
{
var builder = new DbModelBuilder();
builder.Entity<PersonA>();
var model = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));
model.Compile();
}
public class PersonB
{
public int PersonBId { get; set; }
public string Name { get; set; }
}
private void BuildB()
{
var builder = new DbModelBuilder();
builder.Conventions.Remove<IdKeyDiscoveryConvention>();
builder.Entity<PersonB>()
.HasKey(p => p.PersonBId);
var model = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));
model.Compile();
}
public class PersonC
{
public int PersonCId { get; set; }
public string Name { get; set; }
}
private void BuildC()
{
var builder = new DbModelBuilder();
builder.Entity<PersonC>()
.HasKey(p => p.PersonCId);
var model = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2008"));
model.Compile();
}
I get the result of 2.0004ms to 2.0009ms. Curiously, removing conventions made the operation take longer.