How to change an object that was mocked? - c#

In my Unit Test I need to change the value of the object that was mocked before. For example:
public class Cell
{
public int X { get; set; }
public int Y { get; set; }
public string Value { get; set; }
}
public class Table
{
private Cell[,] Cells { get; }
public Table(Cell[,] cells)
{
Cells = cells;
}
public void SetCell(int x, int y, string value)
{
Cells[x, y].Value = value;
}
}
I want to test SetCell method in Table.
So, first I mock Cell, then I create a Cell[,] array of cells, create a Table passing array of cells as a parameter.
SetCell doesn't work, because (I think) I can't change the object that was mocked before. How can I change it?
Here's my test:
ICell[,] cells = new ICell[3, 4];
for (int i = 0; i < cells.GetLength(0); i++)
{
for (int j = 0; j < cells.GetLength(1); j++)
{
var mock = new Mock<ICell>();
mock.Setup(m => m.X).Returns(i);
mock.Setup(m => m.Y).Returns(j);
mock.Setup(m => m.Value).Returns("");
cells[i, j] = mock.Object;
}
}
ITable table = new Table(cells);
table.SetCell(0, 0, "TEST"); // Cannot change it here :/

Setup all the properties so that they can be updated
ICell[,] cells = new ICell[3, 4];
for (int i = 0; i < cells.GetLength(0); i++)
{
for (int j = 0; j < cells.GetLength(1); j++)
{
var mock = new Mock<ICell>();
mock.SetupAllProperties();
mock.Object.X = i;
mock.Object.Y = j;
mock.Object.Value = "";
cells[i, j] = mock.Object;
}
}
//...other code removed for brevity

Related

Is there a way to Translate an array into a dictionary

The problem I'm having is that I'm not sure how to translate my double array into a Dictionary. I have some LINQ Where statements that are pretty heavy, so I wanted to use the keys of my Dictionary to look up a specific value. I have two classes with getters and setters and then my calculator.
I've fiddled around a bit with trying to make either a lookup or a Dictionary, but didn't have any luck.
public class Product
{
public int EarliestOriginYear { get; set; }
public int NoOfDevelopmentYears { get; set; }
public string ProductName { get; set; }
public IEnumerable<ProductIncrementalValue> ProductIncrementalValues { get; set; }
}
public class ProductIncrementalValue
{
public string ProductName { get; set; }
public int OriginYear { get; set; }
public int DevelopmentYear { get; set; }
public double IncrementalValue { get; set; }
}
public IList<double> Calculate(Product product)
{
IList<double> cumulativeDataTriangle = new List<double>();
if (!product.ProductIncrementalValues.Any())
return cumulativeDataTriangle;
for (int i = 0; i < product.NoOfDevelopmentYears; i++)
{
// This is what I want to change (where statements)
var incrementalValues = product.ProductIncrementalValues
.Where(v => v.OriginYear == product.EarliestOriginYear + i)
.ToList();
double previous = 0;
for (int j = 0; j < product.NoOfDevelopmentYears - i; j++)
{
// This is what I want to change
double incrementalValue = incrementalValues.Where(val =>
val.DevelopmentYear == val.OriginYear + j)
.Select(x => x.IncrementalValue)
.FirstOrDefault();
var tmp = incrementalValue + previous;
cumulativeDataTriangle.Add(tmp);
previous = tmp;
}
}
return cumulativeDataTriangle;
}
You could group the products by OriginYear and DevelopmentYear before the loops. Something like this might help:
public IList<double> Calculate(Product product)
{
IList<double> cumulativeDataTriangle = new List<double>();
if (!product.ProductIncrementalValues.Any())
return cumulativeDataTriangle;
var lookup = product.ProductIncrementalValues.ToLookup(v => (v.OriginYear, v.DevelopmentYear), v => v.IncrementalValue);
for (int i = 0; i < product.NoOfDevelopmentYears; i++)
{
var originYear = product.EarliestOriginYear + i;
double previous = 0;
for (int j = 0; j < product.NoOfDevelopmentYears - i; j++)
{
var developmentYear = originYear + j;
var incrementalValues = lookup[(originYear, developmentYear)];
double incrementalValue = incrementalValues.FirstOrDefault();
var tmp = incrementalValue + previous;
cumulativeDataTriangle.Add(tmp);
previous = tmp;
}
}
return cumulativeDataTriangle;
}
Thanks to the previous answer, I managed to implement a Dictionary based on OriginYear and DevelopmentYear, which returns an IncrementalValue.
public IList<double> Calculate(Product product)
{
IList<double> cumulativeDataTriangle = new List<double>();
if (!product.ProductIncrementalValues.Any())
return cumulativeDataTriangle;
var lookup = product.ProductIncrementalValues.
ToDictionary(v => (v.OriginYear, v.DevelopmentYear), v => v.IncrementalValue);
for (int i = 0; i < product.NoOfDevelopmentYears; i++)
{
var originYear = product.EarliestOriginYear + i;
double previous = 0;
for (int j = 0; j < product.NoOfDevelopmentYears - i; j++)
{
var developmentYear = originYear + j;
double incrementalValue;
lookup.TryGetValue((originYear, developmentYear), out incrementalValue);
var tmp = incrementalValue + previous;
cumulativeDataTriangle.Add(tmp);
previous = tmp;
}
}
return cumulativeDataTriangle;
}

Is it possible to get the item index using Contains?

When I use if (moscowCars.Contains(cars[x].Name)) it founds the value in a collection and I believe that not necessary to use moscowCars.RemoveAt(moscowCars.FindIndex(o => o.Equals(cars[x].Name))); to find it for a second time, just: moscowCars.Remove(cars[x].Name);. Of course, I can use try & catch instead of if, but I just want to know can I get the item index using Contains?
using System.Collections.Generic;
namespace Autoworld
{
class GoodCars
{
static List<Tech> cars = new List<Tech>();
public class Tech
{
public string Name { get; set; }
public double KM { get; set; }
}
static void Main()
{
List<string> moscowCars = new List<string>
{
"GAZ-330811 Aper", "Lada Vesta Sport"
};
cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 });
for (int x = 0; x < cars.Count; x++)
{
if (moscowCars.Contains(cars[x].Name))
{
moscowCars.RemoveAt(moscowCars.FindIndex(o => o.Equals(cars[x].Name)));
}
}
}
}
}
You could remove the two-step process entirely and just use .Remove which will return:
true if item is successfully removed; otherwise, false. This method
also returns false if itemwas not found in the List.
This would then look like:
for (int x = 0; x < cars.Count; x++)
{
moscowCars.Remove(cars[x].Name);
}
And if you need to handle the case where no car is found to be removed, you can wrap that call in an if condition like:
for (int x = 0; x < cars.Count; x++)
{
if (!moscowCars.Remove(cars[x].Name))
{
// Handle no cars to remove
}
}
Worth noting that behind the scenes, .Remove ultimately just gets the index and then removes the item at that index (which is what you were originally trying to do anyways):
public bool Remove(T item) {
int index = IndexOf(item);
if (index >= 0) {
RemoveAt(index);
return true;
}
return false;
}
See here for the source.
Alternatively, as others have stated, if you expect the List to contain more than item to be removed, you can use .RemoveAll:
moscowCars.RemoveAll(y => y == cars[x].Name);
And again, to handle the case where nothing is found:
if (moscowCars.RemoveAll(y => y == cars[x].Name) == 0)
{
// Handle no cars to remove
}
You can indeed use IndexOf(item)
this will give you the index of the item, or -1 if 'item' was not found (making this method double as a "contains" as well)
Use simply RemoveAt if you are sure you don't have any duplicated items anyway use the second way.
Solution
static List<Tech> cars = new List<Tech>();
public class Tech
{
public string Name { get; set; }
public double KM { get; set; }
}
static void Main()
{
List<string> moscowCars = new List<string>
{
"GAZ-330811 Aper", "Lada Vesta Sport"
};
cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 });
for (int x = 0; x < cars.Count; x++)
{
if (moscowCars.Contains(cars[x].Name))
{
moscowCars.RemoveAt(moscowCars.IndexOf(cars[x].Name));
}
}
}
Solution
static List<Tech> cars = new List<Tech>();
public class Tech
{
public string Name { get; set; }
public double KM { get; set; }
}
static void Main()
{
List<string> moscowCars = new List<string>
{
"GAZ-330811 Aper", "Lada Vesta Sport"
};
cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 });
for (int x = 0; x < cars.Count; x++)
{
if (moscowCars.Contains(cars[x].Name))
{
moscowCars.RemoveAll(o => o == cars[x].Name);
}
}
}
I hope it will help.

Iterate through ObservableCollection of class

I'm assigning values to a class by using ObservableCollection.Class contains MainItems and it's SubItems. Now how can I read all SubItems for each input of MainItem?
public class MainItems
{
public string ItemName { get; set; }
public ObservableCollection<SubItems> SubItemsList { get; set; }
}
public class SubItems
{
public string SubItemName { get; set; }
}
ObservableCollection<MainItems> _data = new ObservableCollection<MainItems>();
for (int i = 1; i <= 5; i++)
{
MainItems _mainItems = new MainItems();
_mainItems.ItemName = "Main" + i.ToString();
_mainItems.SubItemsList = new ObservableCollection<SubItems>();
for (int j = 1; j <= 3; j++)
{
SubItems _subItems = new SubItems()
{
SubItemName = "SubItem" + i.ToString()
};
_mainItems.SubItemsList.Add(_subItems);
}
_data.Add(_mainItems);
}
The foreach loop alway honors the collections(List, Array, Dictionary(special), ...) boundaries and iterates over all Elements, so its the shortest way to achieve what you want. It disallows you to add/remove elements from the currently iterated collection. In this case the classic for loop is your friend.
Full description from Microsoft:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/foreach-in
Based on Fangs comment:
// foreach Version
foreach (MainItems mainItem in _data)
{
foreach (SubItems subItems in mainItem.SubItemsList)
{
Console.WriteLine($"{mainItem.ItemName} has a child {subItems.SubItemName}!");
}
}
// for Version
for (int i = 0; i < _data.Count; i++)
{
MainItems mainItem = _data[i];
for (int k = 0; k < mainItem.SubItemsList.Count; k++)
{
SubItems subItem = mainItem.SubItemsList[k];
Console.WriteLine($"{mainItem.ItemName} has a child {subItem.SubItemName}!");
}
}
// For Enumerator version
// get the input main item
string input = "Main1";
IEnumerable<ObservableCollection<SubItems>> ItemsforSelectedMainIem = _data.Where(x => x.ItemName == input).Select(x => x.SubItemsList);
var e = ItemsforSelectedMainIem.GetEnumerator();
while (e.MoveNext())
{
var v = e.Current.Select(x=>x.SubItemName).ToList();
foreach (var item in v)
{
Console.WriteLine(item);
}
}

ASP.NET MVC 5 Editor for 2-dimensional array

I have a model with two-dimensional array in it:
public class Matrix
{
public ValidInt[][] Data;
[Range(0, 8, ErrorMessage = "Введите ширину картины")]
public int Width { get; set; }
[Range(0, 8, ErrorMessage = "Введите ширину картины")]
public int Height { get; set; }
public Matrix(int w, int h)
{
Width = w;
Height = h;
Data = new ValidInt[w][];
for (int i = 0; i < w; i++)
this.Data[i] = new ValidInt[h];
}
public class ValidInt
{
[Range(0, 8, ErrorMessage = "Введите число, соответствующее цвету")]
public int Value { get; set; }
public ValidInt()
{
Value = 0;
}
}
}
Then I would like to have HTML.EditorFor to fill data in each block, so I write something like that:
<table>
#for (int column = 0; column < Model.Data.GetLength(1); column++)
{
<tr>
#for (int row = 0; row < Model.Data.GetLength(0); row++)
{
<td>#Html.EditorFor(x => Model.Data[column, row].Value); </td>
}
</tr>
}
</table>
But turns out you can't have EditorFor for two dimensional arrays. Any ideas on how to bypass that?
You cannot use two-dimensional array. However, you could use Jagged Array.
FYI: In order for ModelBinder to bind values to a model, it must have a parameterless constructor.
Model
public class Matrix
{
public int[][] Data { get; set; }
}
View
#using (Html.BeginForm())
{
<table>
#for (int column = 0; column < Model.Data.Length; column++)
{
<tr>
#for (int row = 0; row < Model.Data[column].Length; row++)
{
<td>#Html.EditorFor(x => Model.Data[column][row])</td>
}
</tr>
}
</table>
<button type="submit">Submit</button>
}
Controller
public IActionResult Index()
{
int w = 3, h = 2;
var matrix = new Matrix();
matrix.Data = new int[w][];
for (int i = 0; i < w; i++)
matrix.Data[i] = new int[h];
return View(matrix);
}
[HttpPost]
public IActionResult Index(Matrix matrix)
{
return View(matrix);
}
Result

Using Lists as method arguments [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am making a basic city builder game (in console). I am having a problem with a method (DrawMap). I cant get the lists to work as input arguments to the method. I get a whole bunch of errors, so here is the code.
EDIT: It works now, thank you kmatyaszek.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace City
{
public class map
{
public int m { get; set; } //Map size
public List<int> info { get; set; }
public List<int> fire { get; set; }
public List<int> police { get; set; }
public List<int> education { get; set; }
public List<int> health { get; set; }
public List<int> cursor { get; set; }
}
class Program
{
static void Main(string[] args)
{
map map1 = new map();
map1.m = 256;
map1.info = new List<int>();
for (int i = 0; i < map1.m; i++)
{
map1.info.Add(0);
}
map1.fire = new List<int>();
for (int i = 0; i < map1.m; i++)
{
map1.fire.Add(0);
}
map1.police = new List<int>();
for (int i = 0; i < map1.m; i++)
{
map1.police.Add(0);
}
map1.education = new List<int>();
for (int i = 0; i < map1.m; i++)
{
map1.education.Add(0);
}
map1.health = new List<int>();
for (int i = 0; i < map1.m; i++)
{
map1.health.Add(0);
}
map1.cursor = new List<int>() { 0, 0 };
DrawMap(map1.info, map1.cursor);
}
static void DrawMap(List<int> map1.info, List<int> map1.cursor)
{
int j = 0;
int k = 0;
for (int k = 0; k < Math.Sqrt(map1.m); k++)
{
Console.SetCursorPosition(map1.cursor[j], map1.cursor[k]);
for (int j = 0; j < Math.Sqrt(map1.m); j++)
{
Console.SetCursorPosition(map1.cursor[j], map1.cursor[k]);
Console.Write("A");
}
}
}
}
}
You should read about C# methods (https://msdn.microsoft.com/en-us/library/ms173114.aspx).
I think that method DrawMap should take map object:
...
map1.health = new List<int>();
for (int i = 0; i < map1.m; i++)
{
map1.health.Add(0);
}
map1.cursor = new List<int>() { 0, 0 };
DrawMap(map1);
}
static void DrawMap(map map1)
{
int j = 0;
int k = 0;
for (k = 0; k < Math.Sqrt(map1.m); k++)
{
Console.SetCursorPosition(map1.cursor[j], map1.cursor[k]);
for (j = 0; j < Math.Sqrt(map1.m); j++)
{
Console.SetCursorPosition(map1.cursor[j], map1.cursor[k]);
Console.Write("A");
}
}
}
...
In DrawMap you declare two locals (j and k) in the same scope. You can't do that.
Here you can read about local variable and scope:
https://blogs.msdn.microsoft.com/samng/2007/11/09/local-variable-scoping-in-c/
I don't know where to begin. Let's start with the parameters of the DrawMap method. C# does not allow . in variable names. When you declare the signature of a method you write only names for the parameters. Don't try to reference existing variables in your program. Just choose a name. The compiler will know quick list you mean when you pass them in the call of the method:
DrawMap(map1.info, map.cursor);
After you have given proper names for the parameters of your method like this:
static void DrawMap(List<int> info, List<int> cursor)
You can use the names inside the scope of the method.
The second thing is that you declare your index variables in the method twice. Look at your for-loop declaration. There you have int k=0; k<... that means that a new variable with the same name is declared. Just delete the two variables above the loops.

Categories

Resources