I am testing my class. My method returns an array of insurance percentage paid and financial limit for the given policy id.
For policy id 43 its financial limit is null and its percentage insurance paid is 95.75.I am trying to test this but my test keep failing. Could any one tell where am doing wrong?
here is my class
public class PatientInsuranceLimits : System.Web.UI.Page
{
String sqlConStr = ConfigurationManager.ConnectionStrings["connectionname"].ToString();
public String[] generalLimits(String policyID)
{
String []resultset = new String[2];
SqlConnection con = new SqlConnection(sqlConStr);
String sqlQuery1 = "Select InsurancePaidPercentage as iPP, FinancialLimit as fLimit from Policy where ID=#poid";
SqlCommand cmd1 = new SqlCommand(sqlQuery1, con);
cmd1.Parameters.AddWithValue("#poid", policyID);
try
{
con.Open();
SqlDataReader r = cmd1.ExecuteReader();
while(r.Read()){
resultset[0] = r[0].ToString();
resultset[1] = r[1].ToString();
}
r.Close();
}
catch(Exception ex){
}
finally{
con.Close();
}
return resultset;
}
here is my test class
namespace _10_06_13_test
{
[TestClass()]
public class PatientInsuranceLimitsTest
{
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
[DataSource("System.Data.SqlClient", "Data Source=servername_lab;Initial Catalog=IDKit;User ID=userid;Password=password", "mytable", DataAccessMethod.Sequential), TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\Users", "/")]
[UrlToTest("http://localhost:51063/")]
public void generalLimitsTest()
{
SurvivalHealth.PatientInsuranceLimits target = new SurvivalHealth.PatientInsuranceLimits();
string policyID = "43";
string[] expected = new string[] {"95.75"};
string[] actual;
actual = target.generalLimits(policyID);
Assert.AreEqual(expected, actual);
}
}
}
The function returns an array containing null and "19.75".
You need to change the value assigned to expected to { null, "19.75"}.
However if you are using .net 2 or later I would recommend that you change the method to return a tuple to prevent this sort of errors. It is probably also a good idea to store numbers in a numerical data type like decimal.
Related
I am trying to perform unit test on a business logic function of a 3-tier Windows form C# application. But I'm getting this error:
Message: Test method Cognizant.Dotnet.EMS.UnitTest.BusinessAddEmpDtlsTest.TestBusinessAddEmpDtls15 threw exception:
System.InvalidOperationException: The ConnectionString property has not been initialized.
Now I'm new to unit testing. I have created a visual studio unit test project in my solution. Here is my business layer or tier class:
public class BusinessAddEmployee {
DataAddEmployee objDataAddEmp;
public BusinessAddEmployee()
{
objDataAddEmp = new DataAddEmployee();
}
public int BusinessAddEmpDetails(EntityAddEmployee objEntityAddEmployee) {
SqlParameter[] objDataParams = new SqlParameter[5];
objDataParams[0] = new SqlParameter("#EmpId", SqlDbType.Int) {Value = objEntityAddEmployee.EmpID};
objDataParams[1] =
new SqlParameter("#EmpName", SqlDbType.VarChar, 25) {Value = objEntityAddEmployee.EmpName};
objDataParams[2] =
new SqlParameter("#DeptName", SqlDbType.VarChar, 25) {Value = objEntityAddEmployee.DepartmentName};
objDataParams[3] =
new SqlParameter("#Location", SqlDbType.VarChar, 25) {Value = objEntityAddEmployee.Location};
objDataParams[4] =
new SqlParameter("#ContactNumber", SqlDbType.BigInt) {Value = objEntityAddEmployee.ContactNo};
var result = objDataAddEmp.DataAddEmployeeDetails(objDataParams);
return result;
}
}
And here is the Entity layer/tier class for AddEmployee
public class EntityAddEmployee {
public Int32? EmpID { get; set; }
public string EmpName { get; set; }
public string DepartmentName { get; set; }
public string Location { get; set; }
public long? ContactNo { get; set; }
}
The data layer class is this:
public class DataAddEmployee
{
private static string conStr;
private SqlConnection objConnnection;
SqlCommand objCommand;
public DataAddEmployee()
{
conStr = ConfigurationManager.AppSettings["Connection"];
objConnnection = new SqlConnection(conStr);
}
public int DataAddEmployeeDetails(SqlParameter[] objParams) {
objCommand = new SqlCommand("USPEmpDtls", objConnnection);
objCommand.CommandType = CommandType.StoredProcedure;
objCommand.Parameters.AddRange(objParams);
objConnnection.Open();**//This line throws the exception**
int result;
try
{
result = objCommand.ExecuteNonQuery();
}
catch (Exception e)
{
throw new InvalidOperationException();
}
objConnnection.Close();
return result;
}
}
The unit test class is given below:
[TestClass]
public class BusinessAddEmpDtlsTest
{
private BusinessAddEmployee objBusinessAddEmp;
private EntityAddEmployee objEntityAddEmp;
[TestInitialize]
public void Init()
{
objBusinessAddEmp = new BusinessAddEmployee();
objEntityAddEmp = new EntityAddEmployee();
}
[TestMethod]
public void TestBusinessAddEmpDtls15()
{
objEntityAddEmp.EmpID = 11112;
objEntityAddEmp.EmpName = "John Die";
objEntityAddEmp.DepartmentName = "Audit";
objEntityAddEmp.Location = "Dhaka";
objEntityAddEmp.ContactNo = Convert.ToInt64(01999999999);
Assert.AreEqual(1, objBusinessAddEmp.BusinessAddEmpDetails(objEntityAddEmp));//**I have compared with 1 since it is a valid operation**//
}
}
The connection string works fine since I have successfully inserted data into database from the WindowsForm I created. Everything works fine except the unit test function.
Can anyone tell me what is the problem here why is the exception is occurring? I have initialized the connection string in the data layer class constructor.
Connection string appears to be coming from configuration manager
conStr = ConfigurationManager.AppSettings["Connection"];
Confirm you are getting a proper connection string when running the unit test.
If not then check to make sure the unit test project has an app.config file with the settings necessary to exercise the test.
That said, consider reviewing the current design of the code in question as it appears to be tightly coupled to implementation concerns that make it difficult to test in isolation without negative side-effects.
Ok, I have 3 classes: Teacher, Student and Database for that matter. I wanna read data from database and put it in Teacher or Student. So i have to write something like this:
public Teacher dbSelect(string Table="Teacher")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
But i must have this exact Method with Student return:
public Student dbSelect(string Table="Student")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
Now I can write each one in their ViewModel, But I want to put them in Database class. So is there any way to do that?
(I know i can return them in a list and then work with that list, But just wanna know if there is a way or not!)
UPDATE:
I forgot to put dbConnect in here, so:
public List<Teacher> dbConnect(string query)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = new Teacher(null, null, null, null, null, null, null, null);
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
}
conn.Close();
return result.Items;
}
And again the exact thing exist for Student but returning:
public List<Student> dbConnect(string query)
{
...
}
Answer: I had a Base class and of course wanted to return a List with a specific type, So I used #Jauch answer, but with returning the List.
Here is an idea on how to do what you want, adapted from a code of mine:
public class BaseClass<T>
where T : new ()
{
protected List<object> list;
protected string query;
protected PropertyInfo[] fProperties;
protected Assembly fStoreAssembly;
public BaseClass()
{
list = new List<T>();
fStoreAssembly = Assembly.GetAssembly (typeof(T));
fProperties = typeof(T).GetProperties();
}
public void Read()
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
StoreResults (reader);
conn.Close();
}
catch (Exception ex)
{
//deal with the exception here
}
}
//Store results walks through all the records returned and
//creates new instances of the store object and saves in the list,
//using reflection
protected void StoreResults (SQLiteDataReader reader)
{
if (fProperties == null)
throw new Exception ("Store type definition is missing");
while (reader.Read ())
{
object newStoreItem = fStoreAssembly.CreateInstance (typeof(T).FullName);
foreach (PropertyInfo pi in fProperties)
{
string lcName = pi.Name.ToLower ();
if (HasColumn(reader, lcName))
{
if (!reader.IsDBNull(reader.GetOrdinal(lcName)))
pi.SetValue(newStoreItem, reader[lcName], null);
}
}
list.Add (newStoreItem);
}
}
public bool HasColumn (SQLiteDataReader reader, string columnName)
{
foreach (DataRow row in reader.GetSchemaTable().Rows)
{
if (row ["ColumnName"].ToString () == columnName)
return true;
}
return false;
}
}
And here how you would create Teacher and Student
public class TeacherInfo
{
//Properties for store info from database
}
public class Teacher : BaseClass<TeacherInfo>
{
public Teacher ()
: BaseClass()
{
query = "whatever you want here"
}
}
public class StudentInfo
{
//Properties for store info from database
}
public class Student : BaseClass<StudentInfo>
{
public Student ()
: BaseClass()
{
query = "whatever you want here";
}
}
As the Read routine is public, you can call Read from any instance of Teacher or Student.
You can even create them and store as BaseClass and use it directly if you don't need to know if it is a student or a teacher (for common routines, etc)
This is not an extensive example, but just a point in the direction you could use to turn your code more generic.
You can follow the semantics of using interfaces to return the values and then cast the return type to an appropriate one, or use a base class (interfaces would be better, as you can still extend other classes as base classes while implementing the interface). The entity interface can be created as following,
public interface SchoolEntity {
// Provide the similar properties as members of this interface.
}
Then you can implement this interface in your Teacher and Student.
public class Student : SchoolEntity { }
public class Teacher : SchoolEntity { }
Finally, the parameter can be made a bit more clearer by using enumerations. They would be more clearer while reading, rather than having the same parameter types. Note that function overloading doesn't consider return type as a signature difference.
enum Entity { Teacher, Student }
And then you can check which data to return.
public SchoolEntity dbSelect(Entity type)
{
switch(type) {
case Teacher:
var query = "SELECT * FROM Teacher";
return dbConnect(query, true);
// Rest of the cases.
}
}
Note that, your SQL statement is open to SQL Injection and anyone can either drop the tables, or perform actions that can be passed to the engine.
Working in a list
Working with the list won't be a good idea. Afterall, what list would you return? Would that be, public List<Teacher> dbSelect or public List<Student> dbSelect? The answer and solution to this is to have a same type backing up these both types.
dbSelect function
Note that you are still returning only Teacher type, then why you are having a Student at all? You should definitely cast it back. As a matter of fact, if I had to develop this. I would have to the dbSelect function to take the Entity as a parameter to keep all of the database requests and processing in a single function.
public List<Teacher> dbConnect(Entity type)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = null; // Can be set to null.
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
string query;
// This way, leave the function to build the query.
if(type == Entity.Teacher) {
query = "SELECT * FROM Teacher";
} else {
query = "SELECT * FROM Student";
}
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
if(type == Entity.Teacher) {
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
} else {
// Add the student.
}
}
conn.Close();
return result;
}
Now in this code, you are aware result is of type Teacher. There was no list there and this made your code a bit confusing. Take my advice: Re-write the code.
Please also go through the following useful links:
Explicit Interface Implementation
https://en.wikipedia.org/wiki/SQL_injection
Signatures and overloading
I'm reading some data from a database (information on properties) and i store the information in Property objects. I put the objects in a list of type Property and i display the contents of the list in a listbox. However instead of getting different data for each object I'm getting the same data multiple times. Ps. I instantiate the Property object inside the while loop and the issue persists.
void fillListBoxWithProperties()
{
List<Property> propList = new List<Property>();
db_connection();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "select * from property ";
cmd.Connection = connect;
MySqlDataReader dr = cmd.ExecuteReader();
while(dr.Read())
{
Property prop = new Property();
prop.PropId = Convert.ToInt32(dr["propertyId"]);
prop.Address = dr["Address"].ToString();
prop.PropType = dr["PropertyType"].ToString();
propList.Add(prop);
}
foreach(Property details in propList)
{
lstBoxProperties.Items.Add(String.Format("{0} {1}", details.PropId, details.Address));
}
}
What the list box prints
If i add this code to the loop just for testing:
Property prop = new Property();
prop.PropId = Convert.ToInt32(dr["propertyId"]);
prop.Address = dr["Address"].ToString();
prop.PropType = dr["PropertyType"].ToString();
propList.Add(prop);
//added code
foreach (Property o in propList)
{
Console.WriteLine(o.toString());
}
The result in the console is the following:
Ballyare,
Rathmulan,
Rathmulan,
Letterkenny,
Letterkenny,
Letterkenny,
Convoy,
Convoy,
Convoy,
Convoy,
Gweedore,
Gweedore,
Gweedore,
Gweedore,
Gweedore,
Glenties,
Glenties,
Glenties,
Glenties,
Glenties,
Glenties,
Property Class Code:
class Property
{
private static int _propId =0;
private static string _address="";
private static string _propType="";
public Property()
{
}
public int PropId
{
get { return _propId; }
set { _propId = value; }
}
public string Address
{
get { return _address; }
set { _address = value; }
}
public string PropType
{
get { return _propType; }
set { _propType = value; }
}
}
Well, now after you added the Property class, it's quite clear why all of your instances seem to have the same content. You made your private members holding the data static. So they don't exist separately for each instance but only once for all instances of the class. Remove the static keyword (and see some introduction for what it does)
I have a problem with calling a method void for a string.
I've created a class:
public string SendData(string val1){ return val1; }
public void RecoverBirth()
{
clsConnectionClass conn = new clsConnectionClass();
SqlCommand cmd = new SqlCommand();
SqlDataReader dr;
cmd.CommandText = "select * from birthday";
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
SendData(dr[1].ToString() + " " + dr[2].ToString() + "\r\n");
}
}
}
}
And then I try to retrieve the data from the class
private void button_Click(object sender, EventArgs e)
{
var _test = new Test();
string Result = _test.RecoverBirth();
}
This error occurs:
Can't convert method "void" to "string"
I need RecoverBirth method to be Void not "string", because it has a lot of different cycle and not everything return something, and if I declare it as string I have to use a lot of return null.
Is there a (better) way to do this?
public class Test
{
public string StringValue { get; set;}
public void DoSome()
{
while(some code here)
{
//something here
//set StringValue to what you like
this.StringValue = "this is now the text";
}
}
}
and then
private void button_Click(object sender, EventArgs e)
{
var test = new Test();
test.DoSome();
var result = test.StringValue;
}
The void keyword in the C# language indicates that a method returns nothing.
You should use the return keyword which means that a method returns only one value. What type of return value of the method you should specify at signature of the method. For example:
public string MethodA(bool isItReally)
In the above code return value is type of string.
So, you should correct the method like that:
Your updated code:
class Test
{
public string RecoverBirth()
{
clsConnectionClass conn = new clsConnectionClass();
SqlCommand cmd = new SqlCommand();
SqlDataReader dr;
cmd.CommandText = "select * from birthday";
dr = cmd.ExecuteReader();
string colValue;
if (dr.HasRows)
{
while (dr.Read())
{
colValue= dr[1].ToString() + " " + dr[2].ToString() + "\r\n");
}
}
return colValue;
}
}
It is not possible to assign to a string variable a value of void method as
void method returns nothing.
You better start with basic ... It's very basic things in programming dude..
class Test
{
public string s1(string val) { return val; }
public string DoSome()
{
while(some code here)
{
s1(result1 + result2);
}
//Must return string to get as string
return someVariableOfString;
}
}
If you strictly want your method to be of void return type then pass parameter by reference with out keyword to the method, and in this case method can directly change the reference value and so you can get the new value back in 'calling' code.
You can learn more on out in MSDN
public void DoSome(out string result)
{
//Do whatever stuff you want and assign the new value(string in your case) to the parameter
result = "My new string after some processing.";
}
Calling:
string result;
DoSomething(out result); //After successful execution of this line `result` will have newly assigned string value from within the function
Hope this help you..
Ignoring all the nagging doubts about a design where something like this makes sense... you could use an argument to emit whatever output necessary. For example:
public void DoSomething(Action<string> someAction = null)
{
// When it's time to emit a result, just do
if (someAction != null) someAction("Hello world!");
}
Which you can then call as
var sb = new StringBuilder();
DoSomething(s => sb.AppendLine(s));
If you're calling from a place that doesn't care about the "return value", you can just omit the argument:
DoSomething();
But seriously, your design needs lots of work if you have to do something like this. Also, there's nothing wrong with return null - it's hard to see why that would be an issue in your code. Just replace all those return; with return null; or something. But it seems like your method simply does way too many things if you care about the distinction.
If you need your method to return void, you could use the out keyword to pass in your result as a reference variable, like this:
class Test
{
public string SendData(string val1){ return val1; }
public void RecoverBirth(out string result)
{
clsConnectionClass conn = new clsConnectionClass();
SqlCommand cmd = new SqlCommand();
SqlDataReader dr;
cmd.CommandText = "select * from birthday";
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
result += SendData(dr[1].ToString() + " " + dr[2].ToString() + "\r\n");
}
}
}
}
And your call:
private void button_Click(object sender, EventArgs e)
{
var _test = new Test();
string result = null;
_test.RecoverBirth(out result);
}
First of all, sorry (AGAIN) for my bad english.
Hello. I am still pretty new to C#.NET and we are now tasked by our professor to make a simple banking system using an ADO.NET database. My only problem now is that I can't seem to return the values from the PropertyMethod I created.
Here's how it works: I log in using my auto-generated username and password, in which in the next window, I would be able to deposit or withdraw. I wanted to display in my text boxes the retrieved information from the database.
Is there a proper way to return a value from the PropertyMethod? Or could I just employ other ways to properly retrieve the values I want? Thanks for all your answers.
Here is a part of my class library which authenticates login inputs and should return the values I want:
EDIT: I tried to look at the debugger to trace what's happening to the values, but they are returning nulls.
EDIT 2: Removed unnecessary codes.
EDIT 3: Thanks for noticing my errors. I have already fixed them. My program is working fine now.
here is the propery method
#region pm
public string FinalName
{
get { return finalName; }
set { finalName = value; }
}
public string FinalUname
{
get { return finalUname; }
set { finalUname = value; }
}
public string Acnum
{
get { return acnum; }
set { acnum = value; }
}
public string Pass
{
get { return pass; }
set { pass = value; }
}
public string Actype
{
get { return actype; }
set { actype = value; }
}
public string Mname
{
get { return mname; }
set { mname = value; }
}
public string Lname
{
get { return lname; }
set { lname = value; }
}
public string Fname
{
get { return fname; }
set { fname = value; }
}
decimal bal;
public decimal Bal
{
get { return bal; }
set { bal = value; }
}
public bool Dup
{
get { return dup; }
set { dup = value; }
}
#endregion
and here is the code for authenticating login.
public bool authenticateData(string uname, string pass)
{
bool found = false;
mySqlConnection.Open();
SqlCommand readData = new SqlCommand("AuthenticateLogin", mySqlConnection);
readData.CommandType = CommandType.StoredProcedure;
readData.Parameters.Add("#Username", SqlDbType.NVarChar).Value = uname;
readData.Parameters.Add("#Password", SqlDbType.NVarChar).Value = pass;
SqlDataReader dr;
dr = readData.ExecuteReader();
while (dr.Read())
{
found = true;
Actype = dr.GetString(3);
Bal = dr.GetDecimal(5);
Acnum = dr.GetString(6);
FinalName = dr.GetString(0) + " " + dr.GetString(2) + " " + dr.GetString(1);
break;
}
mySqlConnection.Close();
return found;
}
}
}
And here is my windows form:
private void Transact_Load(object sender, EventArgs e)
{
//here is where my bug occurs
txtName.Text = da.finalName;
txtUsername.Text = da.finalUname;
txtActType.Text = da.actype;
txtBal.Text = da.Bal.ToString();
type = txtActType.Text;
}
In your windows form you're accessing properties of an object called da ... but what is that? Are you actually setting da to a class of results anywhere? Your example code doesn't show this anywhere.
In authenticateData you use a datareader to populate some properties with your results, but those properties belong to what - the class that contains the authenticateData method? What is da, and how are you expecting it to have the values of your results?