How to unit test a public void method in C# MVC - asp.net-mvc

I have a public void method, SaveCover2AData(). How can I create a unit test for this type of method?
This is my public method, I am passing a model object as a parameter in this method.
Now I want to create unit test for this method:
public void SaveCover2AData(CASTabCover2a t2a)
{
CASCreateViewModel obj = (CASCreateViewModel)Session["CASQuote"];
t2a.Quote_Exposures = t2a.Quote_Exposures.Where(x => x.Exposure != null || x.ExposurePL != null).ToList();
t2a.Quote_Jurisdictions = t2a.Quote_Jurisdictions.Where(x => x.Jurisdiction_Name != null || x.Country_NamePL != null).ToList();
t2a.Quote_LimtOfIndemnitys = t2a.Quote_LimtOfIndemnitys.Where(x => x.Indemnity != null || x.IndemnityPL != null || x.LimitOfIndemnity_Currency != null).ToList();
t2a.Quote_SubLimitOfIndemnitys = t2a.Quote_SubLimitOfIndemnitys.Where(x => x.Indemnity != null || x.IndemnityPL != null || x.SubLimitOfIndemnity_Currency != null).ToList();
obj.TabCover2a = t2a;
Session.Add("CASQuote", obj);
ViewBag.Quote_Status_ID = JsonConvert.SerializeObject(obj.Quote_Status_ID);
}
The test method I've attempted so far is:
[TestMethod]
public void CASSaveCover2AData()
{
builder.InitializeController(controller);
var CASTabCover2a = new CASTabCover2a();
controller.SaveCover2AData(CASTabCover2a);
Assert.IsTrue(true);
}
When I am debugging this test case I am getting this error:
An exception of type 'System.NullReferenceException' occurred

First, your variable name is invalid here
var CASTabCover2a = new CASTabCover2a();
Second, void methods affects the database, inserts data or deletes data. In this point before run your void method get the counts of total rows in related table. If row count changed, your method works correctly.
If you insert data, total counts of row must be increased. If deleted vice versa.
public void MyTestMethod()
{
var total = db.Cars.Count();
var car = new Car();
db.Save(car);
var total2 = db.Cars.Count();
Assert.True(total2 > total);
}

Related

am working on updating a single attribute in the User Model which is the balance attribute,

how I can update a single value for an already existing row in the db by only having a parameters that I want to add it to this attribute
here is my code for a trivial way but didnt work
public bool BuyBook(int BookId, int UserId, int BookPrice){
using (var ctx = new OnlineBooksEntities())
{
User updatedCustomer = (from c in ctx.Users
where c.UserId == UserId
select c).FirstOrDefault();
updatedCustomer.Balance = BookPrice;
ctx.SaveChanges();
}
this.DeleteBook(BookId);
return true;
}
Add an sql query to the method solves the update aim
public bool BuyBook(int BookId, int UserId, int BookPrice)
{
try
{
using (var ctx = new OnlineBooksEntities())
{
User user = ctx.Users.Where(x => x.UserId == UserId).FirstOrDefault();
BookPrice = (int)user.Balance + BookPrice;
int noOfRowUpdated =
ctx.Database.ExecuteSqlCommand("Update Users set Balance = "+BookPrice+ " where UserId ="+UserId);
}
Updating basically means changing an existing row's value. Since you mentioned EF, you can do this by retrieving the object, changing its value, and saving it back. Thus you can do something like this:
using (var db = new MyContextDB())
{
var result = db.Books.SingleOrDefault(b => b.BookPrice == bookPrice);
if (result != null)
{
result.SomeValue = "Your new value here";
db.SaveChanges();
}
}

'System.Linq.IQueryable<NewsSite.Models.Domain.Tbl_News>' does not contain a definition

I Create A News Site With MVC5 But I Have Problem .
in Model i Create A Repository Folder And in this i Create Rep_Setting for
Connect to Tbl_Setting in DataBase .
public class Rep_Setting
{
DataBase db = new DataBase();
public Tbl_Setting Tools()
{
try
{
var qGetSetting = (from a in db.Tbl_Setting
select a).FirstOrDefault();
return qGetSetting;
}
catch (Exception)
{
return null;
}
}
}
And i Create a Rep_News for Main Page .
DataBase db = new DataBase();
Rep_Setting RSetting = new Rep_Setting();
public List<Tbl_News> GetNews()
{
try
{
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals("News")
select a).OrderByDescending(s => s.ID).Skip(0).Take(RSetting.Tools().CountNewsInPage).ToList();
return qGetNews;
}
catch (Exception ex)
{
return null;
}
}
But This Code Have Error to Me
OrderByDescending(s=>s.ID).Skip(0).Take(RSetting.Tools().CountNewsInPage).ToList();
Error :
Error 18 'System.Linq.IQueryable<NewsSite.Models.Domain.Tbl_News>' does
not contain a definition for 'Take' and the best extension method overload
'System.Linq.Queryable.Take<TSource>(System.Linq.IQueryable<TSource>, int)' has
some invalid arguments
E:\MyProject\NewsSite\NewsSite\Models\Repository\Rep_News.cs 50 52 NewsSite
How i Resolve it ?
Try it this way. The plan of debugging is to split your execution, this also makes for a more reusable method in many cases. And a good idea is to avoid using null and nullables if you can, if you use them "on purpose" the you must have a plan for them.
DataBase db = new DataBase();
Rep_Setting RSetting = new Rep_Setting();
public List<Tbl_News> GetNews()
{
int skip = 0;
Tbl_Setting tools = RSetting.Tools();
if(tools == null){ throw new Exception("Found no rows in the database table Tbl_Setting"); }
int? take = tools.CountNewsInPage;//Nullable
if(!take.HasValue)
{
// Do you want to do something if its null maybe set it to 0 and not null
take = 0;
}
string typeStr = "News";
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals(typeStr)
select a).OrderByDescending(s => s.ID).Skip(skip).Take(take.Value);
return qGetNews.ToList();
}
if qGetNews is a empty list you now don't break everything after trying to iterate on it, like your return null would. instead if returning null for a lit return a new List<>() instead, gives you a more resilient result.
So I said reusable method, its more like a single action. So you work it around to this. Now you have something really reusable.
public List<Tbl_News> GetNews(string typeStr, int take, int skip = 0)
{
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals(typeStr)
select a).OrderByDescending(s => s.ID).Skip(skip).Take(take);
return qGetNews.ToList();
}
Infact you shjould always try to avoid returning null if you can.
public class Rep_Setting
{
DataBase db = new DataBase();
public Tbl_Setting Tools()
{
var qGetSetting = (from a in db.Tbl_Setting
select a).FirstOrDefault();
if(qGetSetting == null){ throw new Exception("Found no rows in the database table Tbl_Setting"); }
return qGetSetting;
}
}

How to return rows in LINQ and MVC ,

I have model with LINQ that will return Rows. here my code in model class on this query i want to return the result in View. how can i do that?
public void retNumRecord(string email, string fname,
string lname, string zip, string pref,
string address, string tel)
{
int _pref = Convert.ToInt32(pref);
var x = (from p in db.eduardo_member_t
where (p.email != null && p.email.Contains(email))
|| (p.fname != null && p.fname.Contains(fname))
|| (p.lname != null && p.lname.Contains(lname))
|| (p.zip != null && p.zip.Contains(zip))
|| (p.pref != null && p.pref == _pref)
|| (p.address != null && p.address.Contains(address))
|| (p.tel != null && p.tel.Contains(tel))
select p);
return x;
}
You need to put that as a model in your view and the call
return View( retNumRecord(...) );
in your action
A void will not return anything. You need an ActionResult.
public ActionResult retNumRecord(....
{
.....
return View(x);
}
This assumes you have a view called 'retNumRecord', if not then:
return View("yourviewname", x);
Or, if this is an ajax call:
return Json(x);
You would call the method in your controller and then return View(retNumRecord(..));
Right click on your controller name and then create a view. Once you are in the view, You can make a for loop to print out each row.
Follow the music store tutorial as it can get you up to speed with MVC3

DateTime manipulation inside Linq to entities query

running this code:
public bool CheckTime(DateTime date, int UserID, int TotalTimeMin)
{
using (var context = new myDB())
{
var assginments = from c in context.Assignments.Where(x=>(x.AssignmentDateTime < date && x.AssignmentDateTime.Value.AddMinutes(TotalTimeMin) > date) ||
(x.AssignmentDateTime < date.AddMinutes(TotalTimeMin))) select c;
if(assginments != null) return false;
else return true;
}
}
I get this error.
LINQ to Entities does not recognize the method 'System.DateTime AddMinutes(Double)' method, and this method cannot be translated into a store expression.
TotalTimeMin is int. I am not sure what cause this:
AssignmentDateTime is DateTime? and maybe this is the problem ?
Use EntityFunctions.AddMinutes (requires EF 4):
public bool CheckTime(DateTime date, int UserID, int TotalTimeMin)
{
using (var context = new myDB())
{
var assginments = context.Assignments
.Where(x=>(x.AssignmentDateTime < date
&& EntityFunctions.AddMinutes(x.AssignmentDateTime,TotalTimeMin) > date)
|| (x.AssignmentDateTime < date.AddMinutes(TotalTimeMin)));
if(assginments != null) return false;
else return true;
}
}
Note that assignments will never be null (but it might be empty -- test assignments.Any()).

General solution to updating fields for table in Entity Framework 4.0

I want to create a method which can takes the properties I possibly may update and leaving those not interested untouched.
Here is what I did:
public static void updateTable(int id, string field1, string field2, string field3){
using(var context = new Entities()){
var obj = context.Table.Where(x=>x.id == id).FirstOrDefault();
if(obj != null){
obj.field1 = field1;
...
obj.SaveChanges();
}
}
}
But in this pattern, I need to pass all 4 parameters into the method even I just want to update only one field. Is there any generic solution to update only the fields I passed in?
I came up something like this:
public static void updateTable(int id, object data_json){
using(var context = new Entities()){
var obj = context.Table.Where(x=>x.id == id).FirstOrDefault();
if(obj != null){
if(data_json['field1']!=null) //something like this
obj.field1 = data_json['field1'];
...
obj.SaveChanges();
}
}
}
But this can't handle the case that I do want to set a field to be null. Or is there any better solution?
If you don't care about updating relationships, you can use ApplyCurrentValues, which only updates the scalar properties.
E.g:
public static void updateTable(int id, object data_json){
using(var context = new Entities()) {
var obj = context.Table.Where(x=>x.id == id).FirstOrDefault();
context.ApplyCurrentValues("Table", data_json);
}
}
It assumes an entity with the same key is already attached in the graph. In this case, the query for var obj will ensure the object is in the graph, then it's contents are overridden with the scalar properties on the supplied object.
You might need an explicit cast on data_json to ensure it is of the same type contained in the entity set.
Using an ExpandoObject would allow you to send in only the properties you want to set, and would allow you to specify null values as well.
For example:
public static void updateTable(int id, dynamic data){
using(var context = new Entities()){
var obj = context.Table.Where(x=>x.id == id).FirstOrDefault();
if(obj != null){
if (((IDictionary<string, object>)data).ContainsKey("field1"))
obj.field1 = data.field1;
...
obj.SaveChanges();
}
}
}
and you could call it like this:
dynamic data = new ExpandoObject();
data.field1 = 123;
data.field2 = null;
data.field5 = "abc";
MyClass.updateTable(1, data);
Everything can be solved with a moment of reflection. This function solves the problem:
public void UpdateTable(int id, object values)
{
using (var entities = new MyEntities())
{
var valuesType = values.GetType();
var element = entities.MyTable.Where(t => t.ID == id).First();
//We are iterating through all properties of updated element and checking
//if there is value provided for there properties in values parameter
foreach (var property in element.GetType().GetProperties())
{
var valuesProperty = valuesType.GetProperty(property.Name);
//If values contain this property
if (valuesProperty != null)
{
//taking value out of values parameter
var value = valuesProperty.GetValue(values, null);
//setting it in our element to update
property.SetValue(element, value, null);
}
}
entities.SaveChanges();
}
}
Usage:
UpdateTable(125, new { FieldA = 1, FieldB = "ABCD" });
You can even make this method more universal by adding generic table type parameter.

Resources