NSubstitute Returns method and arrays - c#

so I want to test roll results of dice set, but i can't pass an array as arg in Returns method like this:
[TestCase(new[]{2, 2, 3, 1, 5}, Category.Yahtzee, 0)]
public void AddPoints_ForGivenCategory_PointsAreStored(
int[] rollResults, Category selectedCategory, int expectedScore)
{
_randomizer.GetRandomNumber(MIN_VALUE, MAX_VALUE).Returns(rollResults); //<-rollResults not allowed
IDice[] dice = MakeNewDiceSet();
_game.NewGame("A");
_game.RollDice(dice);
_game.AddPoints(selectedCategory);
var result = _game.GameStatus().First()[selectedCategory];
Assert.AreEqual(expectedScore, result);
}
any tips or workarounds for this problem? Or am I forced to do this:
[TestCase(2, 2, 3, 1, 5, Category.Yahtzee, 0)]
public void AddPoints_ForGivenCategory_PointsAreStored(
int die1, int die2, int die3, int die4, int die5, Category selectedCategory, int expectedScore)
{
_randomizer.GetRandomNumber(MIN_VALUE, MAX_VALUE).Returns(die1, die2, die3, die4, die5);
IDice[] dice = MakeNewDiceSet();
/ ...
}
Using NSubstitute v3.1.0.0

NSubstitute does not have Returns<T>(T[] values) (or similar). Instead it has Returns<T>(T initialValue, params T[] otherValues) to indicate we should always specify at least one value to return. The aim at the time was to avoid the potentially confusing case of stubbing a call with "no values" in the case of an empty collection. (Is it a no-op? Or does it clear the call?)
There are a few ways to get the behaviour you want. One way is to split the values into "first" and "rest":
random.GetRandomNumber(1, 10)
.Returns(rollResults.First(), rollResults.Skip(1).ToArray());
Another approach is to use a Queue and stub GetRandomNumber() to consume this:
var rolls = new Queue<int>(rollResults);
random.GetRandomNumber(1, 10).Returns(_ => rolls.Dequeue());
If this is something you need frequently it might be worth creating your own Returns extension that explicitly defines how the empty case should be handled.

Related

C# specify only second optional argument and use the default value for first [duplicate]

Is there a way to set up a C# function to accept any number of parameters? For example, could you set up a function such that the following all work -
x = AddUp(2, 3)
x = AddUp(5, 7, 8, 2)
x = AddUp(43, 545, 23, 656, 23, 64, 234, 44)
Use a parameter array with the params modifier:
public static int AddUp(params int[] values)
{
int sum = 0;
foreach (int value in values)
{
sum += value;
}
return sum;
}
If you want to make sure there's at least one value (rather than a possibly empty array) then specify that separately:
public static int AddUp(int firstValue, params int[] values)
(Set sum to firstValue to start with in the implementation.)
Note that you should also check the array reference for nullity in the normal way. Within the method, the parameter is a perfectly ordinary array. The parameter array modifier only makes a difference when you call the method. Basically the compiler turns:
int x = AddUp(4, 5, 6);
into something like:
int[] tmp = new int[] { 4, 5, 6 };
int x = AddUp(tmp);
You can call it with a perfectly normal array though - so the latter syntax is valid in source code as well.
C# 4.0 also supports optional parameters, which could be useful in some other situations. See this article.
1.You can make overload functions.
SomeF(strin s){}
SomeF(string s, string s2){}
SomeF(string s1, string s2, string s3){}
More info: http://csharpindepth.com/Articles/General/Overloading.aspx
2.or you may create one function with params
SomeF( params string[] paramArray){}
SomeF("aa","bb", "cc", "dd", "ff"); // pass as many as you like
More info: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params
3.or you can use simple array
Main(string[] args){}

Using IComparable to compare arrays

I have a problem with a school task.
"Let's say class List are constructors to generate random arrays.
Class List1 inherits from class List and uses IComparable to compare first elements, then second ones etc. (blank is a 0) {1,1,1}<{1,2}<{2}
Class List2 inherits likewise and compares sizes of arrays by size. If sizes are the same, check like in List1 {1,2,3}<{1,2,3,4}<{2,2,3,4}"
I made class List.
public List(int b)
{
tabb = new int[b];
for (int i = 0; i < b; i++)
tabb[i] = r1.Next(0, 100);
}
I noticed that inheriting from List to List1 the constructors are not inherited, so i dont know where and how to use IComparable
class List1 : List,IComparable<List1>
{
public int CompareTo(List1 x){
return this.CompareTo(x);
}
}
I noticed that inheriting from List to List1 the constructors are not inherited, so i dont know where and how to use IComparable
I can't comprehend that sentence as a single question, as the lack of constructors being inherited seems completely independent to me of how to use IComparable<T>.
So, let's address the two questions separately:
You are correct that constructors are not inherited. That is, while they still exist, they are callable only by the derived type, and not directly usable by outside code. If a base class does not have a parameterless constructor, then as the implementer of the derived class, it is your responsibility to provide a constructor and then call the appropriate base class constructor (every class will have some constructor). For example:
class List1 : List
{
public List1(int count) : base(count) { }
}
(I'm assuming here that List is some type other than the .NET List<T> type, i.e. it's not generic and is defined in your own context.)
In this way, you provide the necessary constructor, and ensure that the correct base constructor is called, by using : base(count) to pass the parameter value to your constructor.
How to use IComparable<T>. It seems to me that this is the crux of your assignment. I would be doing you a disservice to write the code for you. However, I'll try to elaborate on the instructions to help you understand what they seem to be asking (of course, your teacher is the best person for you to receive this advice from).
You have two different assignments here. Both require that you implement the interface IComparable<T>, so the first thing you need to do is make sure you understand what it means to implement an interface. Do you? An interface is a kind of "contract". In any interface declaration, there are described the members that an implementation of that interface is required to provide. If you look at the definition of IComparable<T>, you'll see it requires implementation of just one member: a CompareTo() method.
So, your assignment comes down to how to implement that method for each of the two required subclasses, List1 and List2. The basic idea of the implementation is the same for both, but the specifics are different.
In the first case, the comparison will order the two instances of List1 according to the contents of the collection where the order of those instances is determined by the ordering of the first non-equal element in the same position of the array in each instance. In the examples given, {1, 1, 1} is treated as "less than" {1, 2} because when you compare the elements at each position for each instance of List1, the first corresponding position where the elements are different is the second position (index 1), where {1, 1, 1} has the value 1 and {1, 2} has the value 2. The value 1 is less than the value 2, so the whole instance of {1, 1, 1} is "less than" the whole instance of {1, 2}. (Unfortunately, the assignment as described in your post is not clear on how to order instances where the underlying list of one is shorter than the underlying list of the other, but has exactly the same values in those element positions. I would make the shorter list be treated as "less than", but that's not unambiguously the only valid way to do it.)
In the second part of the assignment, implementing List2, the only thing that's being compared is the length of the list. This should be much easier to implement than the first part of the assignment, because you have only a single value to compare in each List2 instance, i.e. tabb.Length.
Note that in both cases, you can take advantage of the fact that int also implements IComparable<T>, so you can use its CompareTo() method to determine whether corresponding values in each instance of your class are less than, equal to, or greater than each other.
I hope that that's enough to get you pointed in the right direction. If you need more help than that, you probably should just consult with your instructor. They will know exactly how much help they want to provide to you, while remaining short of actually doing the assignment for you.
Sorry, I didn't mean to go all out on this. But then it just happened. It's late. It interested me, especially the need to be able to test it even though the requirement for random numbers makes it difficult to test.
The solution I came do was to separate the list from how it gets populated. That way for test purposes I can substitute a "populator" that inserts exactly the values I want. That way I can create the scenarios for testing.
// This is the base list - it just requires something to populate it.
public class IntegerList : List<int>
{
public IntegerList(IIntegerListPopulator populator, int size)
{
populator.PopulateList(this, size);
}
}
// Interface and implementation to populate a list with random numbers.
public interface IIntegerListPopulator
{
void PopulateList(List<int> target, int size);
}
public class RandomIntegerListPopulator : IIntegerListPopulator
{
public void PopulateList(List<int> target, int size)
{
var random = new Random();
for (var i = 0; i < size; i++)
{
target.Add(random.Next(0, 100));
}
}
}
// Compares by values, but the populator is injected - needed so that
// the class can be tested.
public class IntegerListThatComparesByValues : IntegerList, IComparable<IntegerListThatComparesByValues>
{
public IntegerListThatComparesByValues(IIntegerListPopulator populator, int size)
: base(populator, size)
{ }
public int CompareTo(IntegerListThatComparesByValues other)
{
return new IntegerListValueComparer().Compare(this, other);
}
}
// Class to perform comparisons by value. There's no real point
// in implementing IComparer since I'm not using it that way,
// but it doesn't hurt.
public class IntegerListValueComparer : IComparer<IntegerList>
{
public int Compare(IntegerList x, IntegerList y)
{
// I made this part up. I don't actually know how
// you want to handle nulls.
if (x == null && y == null) return 0;
if (x == null) return 1;
if (y == null) return -1;
// Always compare the longer one to the shorter.
// if this one is shorter, do the reverse comparison
// and reverse the result.
if (y.Count < x.Count) return -Compare(y, x);
if (x.SequenceEqual(y)) return 0;
for (var index = 0; index < x.Count; index++)
{
var comparison = x[index].CompareTo(y[index]);
if (comparison != 0) return comparison;
}
// If the other list is longer than this one, then assume
// that the next element of this list is 0.
return -y[x.Count];
}
}
public class IntegerListThatComparesByLength : IntegerList, IComparable<IntegerListThatComparesByLength>
{
public IntegerListThatComparesByLength(IIntegerListPopulator populator, int size)
: base(populator, size)
{
}
public int CompareTo(IntegerListThatComparesByLength other)
{
var comparisonByCount = Count.CompareTo(other?.Count ?? 0);
return comparisonByCount != 0
? comparisonByCount
: new IntegerListValueComparer().Compare(this, other);
}
}
// *************************************************************
// These are the concrete classes specified in the requirements.
// *************************************************************
public class RandomIntegerListThatComparesByValues :
IntegerListThatComparesByValues
{
public RandomIntegerListThatComparesByValues(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
public class RandomIntegerListThatComparesByLength :
IntegerListThatComparesByLength
{
public RandomIntegerListThatComparesByLength(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
// *************************************************************
// The rest is all testing.
// *************************************************************
// Allows me to create class instances that contain the numbers
// I specify instead of random numbers so that I can create
// test cases.
public class IntegerListPopulatorTestDouble : IIntegerListPopulator
{
private readonly int[] _values;
public IntegerListPopulatorTestDouble(params int[] values)
{
_values = values;
}
public void PopulateList(List<int> target, int size)
{
target.AddRange(_values.Take(size));
}
}
[TestClass]
public class IntegerListThatComparesByValuesTests
{
[TestMethod]
public void EmptyListsAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0 );
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsWithSameValuesAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsOfSameLengthComparedByFirstNonEqualValue()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
var comparison = list1.CompareTo(list2);
Assert.IsTrue(comparison > 0);
comparison = list2.CompareTo(list1);
Assert.IsTrue(comparison < 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros_Case2()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, -4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) < 0);
Assert.IsTrue(list2.CompareTo(list1) > 0);
}
}
[TestClass]
public class IntegerListThatComparesByLengthTests
{
[TestMethod]
public void ListsAreComparedByLength()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
[TestMethod]
public void ListsOfEqualLengthAreComparedByValue()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
}
I don't know if they teach unit testing in school, but this illustrates why they should. While the logic isn't incredibly difficult, it's likely that the first stab at it isn't going to be perfect. Without creating some test cases to run against this, how could you know if you got it right? How would your instructor know? What if you fix one bug but in doing so break the other test case? And then if you have to debug, every single time you debug you get different random numbers. Scary.
(It was the randomness that really threw me off. If the numbers are always random, how does the instructor expect to observe the results and know that they're correct? It's possible but eyeballing it isn't the most reliable way to know that it works.)
In real life, I wouldn't want to put even slightly complex logic into a production system without having these unit tests to tell me that it works as expected.
Also, when you read a description of requirements it can be confusing and unclear. But assuming that I understood the requirements, now you can look at the unit tests and get a clearer idea of what this code is supposed to do. Otherwise someone else could need to make changes, and if they can't tell what it's supposed to do, they can't tell if they're breaking it. If it turns out that I got the requirements wrong then I can change the tests to fit the right requirements. The tests will fail and then I modify the code until the tests pass.

C# Impossible to convert method group to bool?

public void nbOccurences(int[] base1, int n, int m)
{
foreach (int i in base1)
{
if (n == 32)
{
m++;
}
}
}
static void Main(string[] args)
{
int chiffrebase = 32;
int occurence = 0;
int[] test123 = new int[] { 12, 32, 33, 64, 75, 46, 42, 32 };
Program n1 = new Program();
n1.nbOccurences(test123, chiffrebase, occurence);
Console.WriteLine(nbOccurences);
}
I keep getting a "Impossible to convert from method group to bool" message, what's causing the problem? I'm trying to use the method I made in the main program.
Console.WriteLine(nbOccurences);
nbOccurrences is a mehtod (returning void, by the way).
so compiler complains saying "I need something to print on writeline, maybe you want me to print a bool, but I can't convert a method to a bool"
Also, your nbOccurrences seems to do nothing useful: it iterates on an Array, checks some condition and eventually increase the parameter value. But calling code will not be aware of the m value, which remains internal to your function. You should change your method declaration returning an int (or using an out int m parameter, which would not be my choice)
This is my best guess as to what you're actually aiming at:
public int nbOccurrences(int[] base1, int n)
{
int count = 0;
foreach (int i in base1)
{
if (n == 32)
{
count++;
}
}
return count;
}
static void Main(string[] args)
{
int chiffrebase = 32;
int[] test123 = new int[] { 12, 32, 33, 64, 75, 46, 42, 32 };
int occurrences = nbOccurrences(test123, chiffrebase, occurrence);
Console.WriteLine(occurrences);
}
Your method nbOccurrences didn't return anything before, so how can it be used to do anything? There is a way to use an out or ref parameter to get values back from method via parameters, but you should NOT do that until you are much more expert.
The WriteLine method is looking for a string or something that can be converted to a string or have ToString run on it. Instead, you gave it the name of a method (not the result of a method call, the method itself). How would it know what to do with that?
One invokes a method using parentheses, so pay careful attention to note that nbOccurrences is NOT the same thing as nbOccurrences().
Finally, I'm gambling that you do NOT need new Program. It works, but probably isn't what you want. Instead, just call the method which is in the current, same program as the one you're running, Program.
Finally, while this may be too soon in your C# journey, note that this same task can be performed this way (add using System.Linq;):
static void Main(string[] args)
{
int chiffrebase = 32;
int[] test123 = new int[] { 12, 32, 33, 64, 75, 46, 42, 32 };
int occurrences = test123.Count(i => i == chiffrebase);
Console.WriteLine(occrurences);
}
P.S. Occurrences is spelled with two Rs. Not one.
The Console.WriteLine function has many overloads, one of which is expecting a bool as a parameter.
When you call a function like this
Console.WriteLine(1);
the compiler determines which version of the function you want to call (in my above example it should be the int version.
In your sample code, you simply need to add some brackets so it looks like this if you wanted to call the function.
It's worth noting that your nbOccurrences function does not actually return a value (it's return type is void) so this will likely still fail.
Console.WriteLine(nbOccurences());

Using HashSet<int> to create an integer set

I want to create an class that represents an integer set using a HashSet<int>. I want it to keep track of which values are included in the set using that internal container. I've done this so far:
class SetInteger
{
HashSet<int> intTest= new HashSet<int>();
intTest.Add(1);
intTest.Add(2);
intTest.Add(3);
intTest.Add(4);
intTest.Add(5);
intTest.Add(6);
intTest.Add(7);
intTest.Add(8);
intTest.Add(9);
intTest.Add(10);
}
So, here I think I'm adding some values to the HashSet, but I dont see how this can keep track of which values that are included in the set. Any ideas?
The hash set has a Contains method that allows you to check whether a value is in the set.
In addition, the HashSet<T> implements the ISet<T> interface and therefore provides many methods for working with sets, such as union, intersection and determining if a set of values is a (proper) super- or subset of your set.
HashSet<int> intTest = new HashSet<int>()
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
bool has4 = intTest.Contains(4); // Returns true
bool has11 = intTest.Contains(11); // Returns false
bool result = intTest.IsSupersetOf(new []{ 4, 6, 7 }); // Returns true
By the way, did you know about the collection initializer syntax?
You can also foreach on the set to get each element it contains (in an unspecified order):
foreach(int value in intTest)
{
// Do something with value.
}
Or convert it to an array or mutable list (also in an unspecified order):
int[] arr = intTest.ToArray();
List<int> lst = intTest.ToList();
Hmm...well, a HashSet<T> implements IEnumerable<T>, so you can always do this to figure out "What's already in there":
HashSet<int> intTest= new HashSet<int>();
intTest.Add(1);
intTest.Add(2);
intTest.Add(3);
intTest.Add(4);
intTest.Add(5);
intTest.Add(6);
intTest.Add(7);
intTest.Add(8);
intTest.Add(9);
intTest.Add(10);
var inThereNow = intTest.ToArray(); // [1,2,3,4,5,6,7,8,9,10]
There's also bool Contains(T value) which will tell you if a specific value is in the set, IEnumerable<T> Union(IEnumerable<T> other) which will tell you the "OR" of two sets, IEnumerable<T> Intersect(IEnumerable<T> other) which will tell you the overlap of two sets...pretty much anything in either IEnumerable<T> or ISet<T>
You can use HashSet Contains method tell's if the value already exists!
Example :
if (intTest.Contains(5))
{
// already has the value
}
Us the Contains method: http://msdn.microsoft.com/en-us/library/bb356440.aspx
Hope this helps.
you can try this. you just take a one textbox and two button.
HashSet<int> hs = new HashSet<int>();
private void savedataonhashSet_Click(object sender, EventArgs e)
{
hs.Add(Convert.ToInt16(textBox1.Text));
}
private void checkduplicatevalue_Click(object sender, EventArgs e)
{
if (hs.Contains(00))
{
MessageBox.Show("it is");
}
else
{
MessageBox.Show("not there");
}
}
if you again problem faced just drop your code .....

Pass multiple optional parameters to a C# function

Is there a way to set up a C# function to accept any number of parameters? For example, could you set up a function such that the following all work -
x = AddUp(2, 3)
x = AddUp(5, 7, 8, 2)
x = AddUp(43, 545, 23, 656, 23, 64, 234, 44)
Use a parameter array with the params modifier:
public static int AddUp(params int[] values)
{
int sum = 0;
foreach (int value in values)
{
sum += value;
}
return sum;
}
If you want to make sure there's at least one value (rather than a possibly empty array) then specify that separately:
public static int AddUp(int firstValue, params int[] values)
(Set sum to firstValue to start with in the implementation.)
Note that you should also check the array reference for nullity in the normal way. Within the method, the parameter is a perfectly ordinary array. The parameter array modifier only makes a difference when you call the method. Basically the compiler turns:
int x = AddUp(4, 5, 6);
into something like:
int[] tmp = new int[] { 4, 5, 6 };
int x = AddUp(tmp);
You can call it with a perfectly normal array though - so the latter syntax is valid in source code as well.
C# 4.0 also supports optional parameters, which could be useful in some other situations. See this article.
1.You can make overload functions.
SomeF(strin s){}
SomeF(string s, string s2){}
SomeF(string s1, string s2, string s3){}
More info: http://csharpindepth.com/Articles/General/Overloading.aspx
2.or you may create one function with params
SomeF( params string[] paramArray){}
SomeF("aa","bb", "cc", "dd", "ff"); // pass as many as you like
More info: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params
3.or you can use simple array
Main(string[] args){}

Categories

Resources