How to create Unit Test (include Database) in visual studio 2017? - c#

Here's my code :
public partial class ActivityService
{
public SearchActivityOutput GetActivityFromDbByName(SearchActivityInput input)
{
using (var conn = DbService.GetInstance().GetOpenConnection())
{
var savedActivities = GetSearchResultByNameQuery.GetInstance()
.Execute(conn, new { Name = input.Name });
var activityList = savedActivities.Select(a => new ActivityDetail()
{
Name = a.Name,
City = a.City,
Country = a.Country,
Description = a.Description,
OperationTime = a.OperationTime,
Price = a.Price
}).ToList();
var output = new SearchActivityOutput
{
ActivityList = activityList
};
return output;
}
}
}
How can i create unit test from that class?
my sample unit test for that class:
[TestMethod()]
public void GetActivityFromDbByNameTest()
{
Initializer.Init();
var input = new SearchActivityInput { Name = "Marjan" };
var ActList1 = new ActivityDetail()
{ Name = "Marjan", City = "Bandung", Country = "Indonesia", Description = "coba", OperationTime = "24 Jam", Price = 2000};
var ActList2 = new ActivityDetail()
{ Name = "Marjan", City = "Bandung", Country = "Indonesia", Description = "coba", OperationTime = "24 Jam", Price = 3500 };
var ActList3 = new ActivityDetail()
{ Name = "Marjan aja", City = "Jakarta", Country = "Indonesia", Description = "apapun", OperationTime = "2 Hari", Price = 4500 };
var ActList4 = new ActivityDetail()
{ Name = "Marjan", City = "Stockholm", Country = "Swedia", Description = "123coba", OperationTime = "3 Jam", Price = 3500 };
var ActList5 = new ActivityDetail()
{ Name = "Marjan", City = "Stockholm", Country = "Swedia", Description = "123coba", OperationTime = "3 Jam", Price = 4500 };
var ActList6 = new ActivityDetail()
{ Name = "Marjan aja", City = "Jakarta", Country = "Indonesia", Description = "apapun", OperationTime = "2 Hari", Price = 2000 };
var ActList7 = new ActivityDetail()
{ Name = "Marjan", City = "Stockholm", Country = "Swedia", Description = "123coba", OperationTime = "3 Jam", Price = 3500 };
var ActList8 = new ActivityDetail()
{ Name = "Marjan", City = "Stockholm", Country = "Swedia", Description = "123coba", OperationTime = "3 Jam", Price = 2000 };
var ActList9 = new ActivityDetail()
{ Name = "Marjan", City = "Stockholm", Country = "Swedia", Description = "123coba", OperationTime = "3 Jam", Price = 2000 };
var ActList = new List<ActivityDetail>();
ActList.Add(ActList1);
ActList.Add(ActList2);
ActList.Add(ActList3);
ActList.Add(ActList4);
ActList.Add(ActList5);
ActList.Add(ActList6);
ActList.Add(ActList7);
ActList.Add(ActList8);
ActList.Add(ActList9);
var expectedResult = new SearchActivityOutput
{
ActivityList = ActList
};
using (var conn = DbService.GetInstance().GetOpenConnection())
{
var actualResult = ActivityService.GetInstance().GetActivityFromDbByName(input);
Assert.AreEqual(expectedResult, actualResult);
}
}
but, when i run the unit test, there give some error message :
Test Name: GetActivityFromDbByNameTest Test
Result StackTrace: at
xxxx.ActivityServiceTests.GetActivityFromDbByNameTest()
in
70 Result Message: Assert.AreEqual failed.
Expected:(xxx.yyy.zzz.Model.SearchActivityOutput).
Actual:(xxx.yyy.zzz.Model.SearchActivityOutput).

You should not use the database while your unittesting.
Wikipedia says: A common example of this is classes that depend on a database: in order to test the class, the tester often writes code that interacts with the database. This is a mistake, because a unit test should usually not go outside of its own class boundary, and especially should not cross such process/network boundaries because this can introduce unacceptable performance problems to the unit test-suite.
Use testdata or a dummy class that represent your Database.
https://softwareengineering.stackexchange.com/questions/119367/should-service-test-classes-connect-to-the-database
https://softwareengineering.stackexchange.com/questions/138238/unit-testing-database-coupled-app/138257#138257

You cannot unit test a class that performs any I/O-related tasks. Even if your tests seem to run fine on your development machine, they will likely fail on your colleague's machine or CI server.
In order for your piece of code to be testable, it should be a either a pure function, or it should be reducible to a pure function using some abstraction techniques like IoC / higher order functions / etc.
Learn to write testable code first. This article will give you some advise - https://www.toptal.com/resume/sergey-kolodiy (I'm the author of it).

I completely agree with the other statements about not using the database in your unit tests, but the answer to the failure that you're currently receiving is that you should be using methods of the CollectionAssert class to compare the contents of two collections instead of the Assert class that you're using. If you just want to ensure that the returned List contains the same elements regardless of ordering, you can use
CollectionAssert.AreEquivalent(expectedResult, actualResult);
If sequencing order is important, you should use
CollectionAssert.AreEqual(expectedResult, actualResult);

Related

No access to properties when inserting to child tables in Entity Framework

enter image description here
[WebMethod]
public void AddEmployementRequest(EmployementRequest emp)
{
EmployeeSkill employeeSkill = new EmployeeSkill
{
Skill = emp.,
Description = emp.
};
EmployeeLanguage employeeLanguage = new EmployeeLanguage
{
Name = emp.,
ConversationLevel = emp.
};
EmployeeCours employeeCours = new EmployeeCours
{
Date =emp. ,
Course = emp.,
Duration = emp.,
Association = emp.,
Description = emp.
};
EmployementRequest employementRequest = new EmployementRequest
{
Name = emp.Name,
Address = emp.Address,
Surnam = emp.Surnam,
Father = emp.Father,
IDNumber = emp.IDNumber,
IDCardNumber = emp.IDNumber,
IDCity = emp.IDCity,
Birthday = emp.Birthday,
Birthplace = emp.Birthplace,
Nationality = emp.Nationality,
Religion = emp.Religion,
Phone = emp.Phone,
Cell = emp.Cell,
EmergencyAddress = emp.EmergencyAddress,
EmergencyName = emp.EmergencyName,
EmergencyPhone = emp.EmergencyPhone,
ParentedPeople = emp.ParentedPeople,
Gender = emp.Gender,
MarriageStatus = emp.MarriageStatus,
Residency = emp.Residency,
InsuranceCode = emp.InsuranceCode,
InsuranceStatus = emp.InsuranceStatus,
VehicleType = emp.VehicleType,
MilitaryServiceStatus = emp.MilitaryServiceStatus,
EducatedFrom = emp.EducatedFrom,
EducationField = emp.EducationField,
EducationGrade = emp.EducationGrade,
ExtraWorkCapability = emp.ExtraWorkCapability,
LeisureTimeHobbies = emp.LeisureTimeHobbies,
Salary = emp.Salary,
IntroducerName = emp.IntroducerName,
IntroductionMethod = emp.IntroductionMethod,
Illness = emp.Illness,
VehicleStatus = emp.VehicleStatus,
PKEmploymentRequest = Guid.NewGuid(),
};
employementRequest.EmployeeLanguages.Add(employeeLanguage);
employementRequest.EmployeeSkills.Add(employeeSkill);
employementRequest.EmployeeCourses.Add(employeeCours);
using (var db = new UKN_DBNAMEEntities())
{
db.EmployementRequests.Add(employementRequest);
db.SaveChanges();
}
}
I want to insert to all parent and child tables at once ,As you can see I can't access the properties in child tables and also there's no intellisense to show the properties unlike the parent
I think I need a Linq query but I have no idea
have you tried
[WebMethod]
public void AddEmployementRequest(EmployementRequest emp) {
emp.PKEmploymentRequest = Guid.NewGuid();
using (var db = new UKN_DBNAMEEntities()) {
db.EmployementRequests.Add(emp);
db.SaveChanges();
}
}
It may/should do, but...
Consider:
using automapper or the like;
use some query to avoid recreation of Language or Skil

Static Fields - EasyPost - ClientManager Init

I am currently having a problem when it comes to static fields in C#, the problem is in the way EasyPost instantiates their ClientManger however, I think someone with a better understanding regarding static fields might be able to help me.
I am creating a plugin that allows for multiple users to access EasyPost for tracking off parcels.
I have written a Unit test to test the scenario where multiple people use it at the same time.
Unit Test:
[TestMethod()]
public void TestMultiInit()
{
var Client2 = new cpEasyPost("123");
var Client = new cpEasyPost("123456qq785412");
var Shipment = Client.CreateShipment(
new EasyPost.Address
{
street1 = "417 MONTGOMERY ST",
street2 = "FLOOR 5",
city = "SAN FRANCISCO",
state = "CA",
zip = "94104",
country = "US",
company = "EasyPost"
},
new EasyPost.Address
{
street1 = "417 MONTGOMERY ST",
street2 = "FLOOR 5",
city = "SAN FRANCISCO",
state = "CA",
zip = "94104",
country = "US",
company = "EasyPost"
},
new EasyPost.Parcel
{
length = 20.2,
width = 10.9,
height = 5,
weight = 65.9
});
var Shipment2 = Client2.CreateShipment(
new EasyPost.Address
{
street1 = "417 MONTGOMERY ST",
street2 = "FLOOR 5",
city = "SAN FRANCISCO",
state = "CA",
zip = "94104",
country = "US",
company = "EasyPost"
},
new EasyPost.Address
{
street1 = "417 MONTGOMERY ST",
street2 = "FLOOR 5",
city = "SAN FRANCISCO",
state = "CA",
zip = "94104",
country = "US",
company = "EasyPost"
},
new EasyPost.Parcel
{
length = 20.2,
width = 10.9,
height = 5,
weight = 65.9
});
}
The issue is Client2 has incorrect key so if I try and create a shipment with it should fail however because of ClinetManager being static is uses Client init of it because if was later.
Here is my ctor:
public cpEasyPost(string secretKey)
{
SecretKey = secretKey;
//Original way of init Client
//ClientManager.SetCurrent(SecretKey);
//Create ClientManager
ClientManager.SetCurrent(() => new Client(new ClientConfiguration(SecretKey)));
}
And here is my method:
public Shipment CreateShipment(Address AddressFrom, Address AddressTo, Parcel Parcel, CustomsInfo customs = null, string CustomReference = "", double? InsauranceAmount = null)
{
//Validate Adress
var isValidFrom = ValidateAddress(AddressFrom);
var isValidTo = ValidateAddress(AddressFrom);
if (!isValidFrom.isSuccess)
throw new Exception("Address From is not Valid");
if (!isValidTo.isSuccess)
throw new Exception("Address To is not Valid");
//Validate Pacrcel
var isValidParcel = ValidateParcel(Parcel);
if (!isValidFrom.isSuccess)
throw new Exception("Parcel is not Valid");
//Create Shipment
Shipment shipment = new Shipment()
{
reference = CustomReference,
to_address = AddressTo,
from_address = AddressFrom,
parcel = Parcel,
customs_info = customs
};
//ClientManager.SetCurrent(SecretKey); **
shipment.Create();
//Add Insurance
if (InsauranceAmount != null)
shipment.Insure(InsauranceAmount.Value);
return shipment;
}
No the issue I have is that the ClinetManager is static, this is a locked DDL so I can't modify this. In the method, I considered ssetting the manager before every call however this does not seem like the best solution as it could still theoretically lead to issues I marked this with **.
Any help would be greatly appreciated. Thank you in adnvacne.
At the end, I just rebuild the code from their SDK into something that fitted my needs better. There is no other way around this.

vTiger .net C# sales order fails - MANDATORY_FIELDS_MISSING “message”:"

Throwing an exception when I trying to create sales order in VTiger version 6.15.7.6
Sending the following entity
for Sales order creation
VTigerListItem[] arrListItem = new VTigerListItem[1];
arrListItem[0] = new VTigerListItem() { productid = "25x405", listprice = "468.25", quantity = "1" };
VTigerSalesOrder[] arrListItem1 = new VTigerSalesOrder[1];
arrListItem1[0] = new VTigerSalesOrder()
{
start_period = "2015-01-01",
end_period = "2015-01-01",
subject = "Testing",
contact_id = "4x680",
sostatus = SoStatus.Created,
account_id = "3x679",
assigned_user_id = "19x11",
bill_street = "test bill street",
invoicestatus = Invoicestatus.Created,
productid = "25x405",
cf_1121 = "RDMS",
createdtime = "2015-01-01",
modifiedtime = "2015-01-01",
LineItems = arrListItem
};
var desc = vtigerApi.Create(arrListItem1[0]);
Please check the Contactid , Accountid and Productid.
Module ids are given wrong.
Contacts start with 12X,
Accounts start with 11X,
Products start with 14X,
assign_user_id if it is assigning to User then 19X, if it is assigning to Group then 20X. Also change contact_id to contactid,account_id to accountid.

adding items into list by for loops

I am creating a chart for windows phone 7.
This is the foreach for each hawker returned:
void dbSvc_retrievepopularhawkerCompleted(object sender, RouteServiceRef.retrievepopularhawkerCompletedEventArgs e)
{
List<RouteServiceRef.Hawker> recommendPlaceList;
recommendPlaceList = e.Result.Cast<RouteServiceRef.Hawker>().ToList();
string hawkername = "";
string address = "";
string postal = "";
double coordX = 0.0;
double coordY = 0.0;
double popularity = 0;
foreach (RouteServiceRef.Hawker rp in recommendPlaceList)
{
hawkername = rp.hawkername;
address = rp.address;
postal = rp.postal;
coordX = rp.xcoord;
coordY = rp.ycoord;
popularity = rp.popularity;
}
I have to change the above codes to be inside this list of cities:
List<City> cities = new List<City> { new City { Name = "CLE", Population = 2250871 }, new City { Name = "CMH", Population = 1773120 }, new City { Name = "CVG", Population = 2155137 }, new City { Name = "DET", Population = 4425110 } };
such as: List<City> cities = new List<City> { new City Name = hawkername, Population = popularity }
so that I can do a bind to my chart:
ColumnSeries bs = ChartControl.Series[0] as ColumnSeries; bs.ItemsSource = cities;
I am not sure how to mix them up, can someone guide me along ? As I do not want to hard code the name and population inside.
that's easy, Just follow the code below.
Declare the list of City Above the foreach loop and on each iteration just add new item to the list
List<City> cities = new List<City> ();
foreach (RouteServiceRef.Hawker rp in recommendPlaceList)
{
hawkername = rp.hawkername;
address = rp.address;
postal = rp.postal;
coordX = rp.xcoord;
coordY = rp.ycoord;
popularity = rp.popularity;
cities.Add(new City(){Name = hawkername, Population = popularity });
}
This fills the cities list as well on the completion of foreach loop.

EF Parent Child Inserts

I have the following database tables: Teachers, Subjects, and TeachersSubjects.
All the primary keys are setup properly.
I have a web page and would like to have a quick entry where I can just put in a teacher's name and a list of subjects she will be teaching.
I am using VS2012 Express and Entity Framework.
NorthwindCustEntities context = new NorthwindCustEntities();
Teacher t1 = new Teacher() { Name = "Jane Smith" };
Subject s1 = new Subject() { Name = "Math" };
Subject s2 = new Subject() { Name = "Science" };
context.Subjects.Add(s1);
context.Subjects.Add(s2);
context.Teachers.Add(t1);
context.SaveChanges();
So how do I go from my quick entry page to database in one click and propagate all three tables?
Use the following code:
NorthwindCustEntities context = new NorthwindCustEntities();
Teacher t1 = new Teacher() { Name = "Jane Smith" };
Subject s1 = new Subject() { Name = "Math" };
Subject s2 = new Subject() { Name = "Science" };
context.Subjects.Add(s1);
context.Subjects.Add(s2);
t1.Subjects.Add(s1);
t1.Subjects.Add(s2);
context.Teachers.Add(t1);
context.SaveChanges();
Use this:
// think we have a
string teacherName;
// and a list of
string[] subjectNames;
// then:
NorthwindCustEntities context = new NorthwindCustEntities();
Teacher t1 = new Teacher() { Name = teacherName };
t1.Subjects = new List<Subject>();
foreach(var subject in subjectNames) {
t1.Subjects.Add(new Subject() { Name = subject });
}
context.Teachers.Add(t1);
context.SaveChanges();
Or by your example:
NorthwindCustEntities context = new NorthwindCustEntities();
Teacher t1 = new Teacher() { Name = "Jane Smith" };
Subject s1 = new Subject() { Name = "Math" };
Subject s2 = new Subject() { Name = "Science" };
t1.Subjects.Add(s1);
t1.Subjects.Add(s2);
context.Teachers.Add(t1);
context.SaveChanges();

Categories

Resources