We have an enum:
enum Letters
{
A,
B,
C,
D,
E
}
When I try:
var frozenLetter = fixture.Freeze(Letters.D);
Strangely, frozenLetter == A.
var letter = fixture.Create<Letters>();
var anotherLetter = fixture.Create<Letters>();
Letter and anotherLetter both equal A, so the Letters type has been frozen, but to the first constant in the enum rather than the one specified.
Is there a way to freeze an enum to the constant I wish?
Freeze Inject and Register are slightly different.
Use Inject for the described behavior, as the following test demonstrates:
[Fact]
public void Test()
{
var fixture = new Fixture();
var expected = Letters.D;
fixture.Inject(expected);
var letter = fixture.Create<Letters>();
var anotherLetter = fixture.Create<Letters>();
Assert.Equal(expected, letter);
Assert.Equal(expected, anotherLetter);
}
The problem with the question's sample code is that the parameter (seed) isn't used as the frozen value.
Related
I'm trying to do an xUnit test on a function and it is failing. Went with the debuger and all the values are as expected. the expected result is equal with the actual result. So for the next step, trying to figure out why it is failing, I assigned the same values for the input and the expected result (without using the function I wanted to test) to make sure both are equal then used the function Asser.Equal(expectedResult, input) but again I ended up with an error (the actual and expected results are not the same) even though I made them exactly the same. The tests I'm trying to make is on structures. The next step , after instead of assigning the values for the expectedResult, I just made expectedResult = input and used Assert.Equal(expectedResult, input) and now the tests were successful. My question would be, why doesn't it work when I assign the values separately to the expectedResult and why it does work when I make the expectedResult = with the input. Is this because of the structures from the code?
[Fact]
// this example doesn't work
public void GenerateGeneralRanking_OneSerriesAsInput_ShouldReturnSortedRanking()
{
Contest input = new Contest();
input.GeneralRanking.Contestants = new Contestant[3];
Contestant input1 = new Contestant ( "Ion", "Romania", 9.500 );
Contestant input2 = new Contestant("Alex", "Romania", 9.300);
Contestant input3 = new Contestant("Dan", "Romania", 9.200);
input.GeneralRanking.Contestants[0] = input1;
input.GeneralRanking.Contestants[1] = input2;
input.GeneralRanking.Contestants[2] = input3;
Contest expectedRanking = new Contest();
expectedRanking.GeneralRanking.Contestants = new Contestant[3];
expectedRanking.GeneralRanking.Contestants[0] = input1;
expectedRanking.GeneralRanking.Contestants[1] = input2;
expectedRanking.GeneralRanking.Contestants[2] = input3;
Assert.Equal(input, expectedRanking);
}
And If I make it like this it works ->
[Fact]
public void GenerateGeneralRanking_OneSerriesAsInput_ShouldReturnSortedRanking()
{
Contest input = new Contest();
input.GeneralRanking.Contestants = new Contestant[3];
Contestant input1 = new Contestant ( "Ion", "Romania", 9.500 );
Contestant input2 = new Contestant("Alex", "Romania", 9.300);
Contestant input3 = new Contestant("Dan", "Romania", 9.200);
input.GeneralRanking.Contestants[0] = input1;
input.GeneralRanking.Contestants[1] = input2;
input.GeneralRanking.Contestants[2] = input3;
Contest expectedRanking = new Contest();
expectedRanking.GeneralRanking.Contestants = new Contestant[3];
// This would be the changed part
expectedRanking = input;
Assert.Equal(input, expectedRanking);
}
The function I'm trying to test makes the same thing as the first example of the code, so I typed the values for the sake of the example. Sorry if I missed some info and thank you in advance
I would guess that Contest does not implement IEquatable<Contest> or otherwise override Equals(object). Therefore Assert.Equal will only work when the objects are reference equal. If you don't want to do this, you can create your own IEqualityComparer<Contest> and use the overload Assert.Equal(expectedRanking, input, equalityComparer). Best of luck
I'd suggest to use the Fluent Assertions library for this kind of assert checks in unit tests. Instead of rigid equality, you are looking for equivalency.
Then your assert becomes:
input.Should().BeEquivalentTo(expectedRanking);
and this doesn't look for references, only values!
How can i use a var in c# over {} like:
if
{
var test;
while
{
test = "12345";
//test is defined
}
var test2 = test;
//test is undefined
}
I do not understand it.
You can't use var with uninitialized variable because in this case compiler won't know the real type. var is syntactic sugar - compiler should decide which type to use and in IL code you will see real type.
If you really want var you should initialize it with any value of some type (in your case - string):
if
{
var test = String.Empty; // initialize it - now compiler knows type
while
{
test = "12345";
//test is defined
}
var test2 = test;
//test is undefined
}
You can use object type instead of var then assign null as initialization. It will work for string, int as you wish.
Please check below:
if
{
object test = null;
while
{
test = "12345";
//test is defined
}
var test2 = test;
//test is undefined
}
Please check example in DotNetFiddle.
Var is not a type, var is a keyword that tells the computer to decide which type fits for your value.
You can use this instead:
if
{
var test = "placeholder";
while
{
test = "12345";
//test is defined
}
var test2 = test;
//test is undefined
}
Or better yet, just declare a string from the very start, var is meant to be used when you don't know what type you will need at the point of declaration, when you do know the type you better just declare the reference with the proper type.
Edit:
This code works just fine for me (note that in your original code you were missing the condition
if (true)
{
string test;
while (true)
{
test = "12345";
//test is defined
}
var test2 = test;
//test is undefined
}
Let us say, I have an enum BasicType, which is defined as follows:
public enum ObjectType{
A = 1,
B = 2,
C = 3,
}
The BasicType identifies performs a ternary classification of any Object. Subsequently, I realized that the objects A and B need to be treated in a similar way as compared to C, so I defined another enum ObjectGroupType as follows :
public enum ObjectGroupType
{
AB = 1,
C = 2,
}
With the new enum, I am able to bucket objects of several known types as one. So, when I receive a stream of objects in various types, I actually identify whether they belong to AB or C type. Is there an elegant workaround for this? For instance, will I be able to assign the same enum values for A and B in the ObjectGroupType?:
Edit 1 : I am unable to find the resemblance to the question here
Edit 2 : Thank you Maurice for your constructive inputs -- taking cues from your answer, I came up with this redefined ObjectGroupType.
public enum ObjectGroupType
{
AB = ObjectType.A | ObjectType.B
C = 2,
}
Is this valid?
Essentially, when I process a stream of objects of type AB, I want to ascertain Type A or Type B objects. This is quite similar to a hierarchical two-level decision tree:
object
/ \
AB C
/\
A B
I apologize in advance if I misread your intent, but it almost sounds like you want to allow multiple different enum types to be acted on in your code based on the enum value. The good thing is that you can do that already with bitwise operations and enums.
Given an enum that looks like this:
[Flags]
enum ObjectType
{
A = 1,
B = 2,
C = 4,
D = 8
}
You can set a comparison value that is the bitwise OR of several values:
var allowedValues = ObjectType.A | ObjectType.C;
This works because the values in the enum act like bit fields under the covers.
When you run your code, you do a bitwise AND on the allowedValues variable and the test variable and see if it matches your test variable. If it does, then it is one of the values you want:
if ((test & allowed) == test) ...
Below is a working example using the enum above that shows you how it works.
void Main()
{
var allowed = ObjectType.A | ObjectType.C;
var values = new int [] { 1, 2, 4, 8 };
foreach (var i in values)
{
var test = (ObjectType)i;
if ((test & allowed) == test)
{
Console.WriteLine("Found a match: {0}", test);
}
else
{
Console.WriteLine("No match: {0}", test);
}
}
}
Best of luck!
Edit:
I found the answer of Maurice Reeves very good, I only want to bring some more info:
[Flags]
public enum ObjectType
{
None=0,
A = 1,
B = 2,
C = 4,
D = 8,
E = 16,
AorB=A|B,
BorCorD=B|C|D,
}
By using [Flags] attribute, you can create sets of enum items, which can help you establishing different business rules for each set.
In order to check if and item exist in a set you can do as follow:
public static bool IsAorB(this ObjectType item)
{
return ObjectType.AorB.HasFlag(item);
}
if you want to creat on the fly new set of items, you can do:
var newGroup=ObjectType.A | ObjectType.BorCorD;
if you want to apply some business rule to a set, except an item, you can do:
var newGroupExceptC =newGroup^=ObjectType.C;
Now if you check if element C exist in the set you will get false:
bool exist=newGroupExceptC.HasFlag(ObjectType.C) // =false
more info you can find here
You might use a int instead of an enum, use values that don't overlap when combined (i.e. values whose binary representation has only one bit on) and then perform a mask operation on the ObjectType of a parameter to determine if it is AB:
class SomeClass
{
public static class ObjectType
{
public const int A = 1;
public const int B = 2;
public const int C = 4;
public const int D = 8;
}
public int MyType;
public string Title;
static void Main(string[] args)
{
List<SomeClass> list = new List<SomeClass>()
{
new SomeClass() {Title ="I am of type A", MyType = ObjectType.A }
,new SomeClass() {Title ="I am of type B", MyType = ObjectType.B }
,new SomeClass() {Title ="I am of type AB", MyType = ObjectType.A | ObjectType.B }
};
list.ForEach(p => { if (p.MyType == (ObjectType.A | ObjectType.B)) Console.WriteLine(p.Title); });
}
}
The downside of this approach is losing strong-typing of Object Type, i.e. you can assign any value not just those you define in the ObjectType.
I have a list of string[].
List<string[]> cardDataBase;
I need to sort that list by each list-item's second string value (item[1]) in custom order.
The custom order is a bit complicated, order by those starting characters:
"MW1"
"FW"
"DN"
"MWSTX1CK"
"MWSTX2FF"
then order by these letters following above starting letters:
"A"
"Q"
"J"
"C"
"E"
"I"
"A"
and then by the numbers following above.
a sample, unordered list left, ordered right:
MW1E10 MW1Q04
MWSTX2FFI06 MW1Q05
FWQ02 MW1E10
MW1Q04 MW1I06
MW1Q05 FWQ02
FWI01 FWI01
MWSTX2FFA01 DNC03
DNC03 MWSTX1CKC02
MWSTX1CKC02 MWSTX2FFI03
MWSTX2FFI03 MWSTX2FFI06
MW1I06 MWSTX2FFA01
I tried Linq but I am not that good in it right now and cannot solve this on my own. Do I need a dictionary, regex or a dictionary with regex in it? What would be the best approach?
I think you're approaching this incorrectly. You're not sorting strings, you're sorting structured objects that are misrepresented as strings (somebody aptly named this antipattern "stringly typed"). Your requirements show that you know this structure, yet it's not represented in the datastructure List<string[]>, and that's making your life hard. You should parse that structure into a real type (struct or class), and then sort that.
enum PrefixCode { MW1, FW, DN, MWSTX1CK, MWSTX2FF, }
enum TheseLetters { Q, J, C, E, I, A, }
struct CardRecord : IComparable<CardRecord> {
public readonly PrefixCode Code;
public readonly TheseLetters Letter;
public readonly uint Number;
public CardRecord(string input) {
Code = ParseEnum<PrefixCode>(ref input);
Letter = ParseEnum<TheseLetters>(ref input);
Number = uint.Parse(input);
}
static T ParseEnum<T>(ref string input) { //assumes non-overlapping prefixes
foreach(T val in Enum.GetValues(typeof(T))) {
if(input.StartsWith(val.ToString())) {
input = input.Substring(val.ToString().Length);
return val;
}
}
throw new InvalidOperationException("Failed to parse: "+input);
}
public int CompareTo(CardRecord other) {
var codeCmp = Code.CompareTo(other.Code);
if (codeCmp!=0) return codeCmp;
var letterCmp = Letter.CompareTo(other.Letter);
if (letterCmp!=0) return letterCmp;
return Number.CompareTo(other.Number);
}
public override string ToString() {
return Code.ToString() + Letter + Number.ToString("00");
}
}
A program using the above to process your example might then be:
static class Program {
static void Main() {
var inputStrings = new []{ "MW1E10", "MWSTX2FFI06", "FWQ02", "MW1Q04", "MW1Q05",
"FWI01", "MWSTX2FFA01", "DNC03", "MWSTX1CKC02", "MWSTX2FFI03", "MW1I06" };
var outputStrings = inputStrings
.Select(s => new CardRecord(s))
.OrderBy(c => c)
.Select(c => c.ToString());
Console.WriteLine(string.Join("\n", outputStrings));
}
}
This generates the same ordering as in your example. In real code, I'd recommend you name the types according to what they represent, and not, for example, TheseLetters.
This solution - with a real parse step - is superior because it's almost certain that you'll want to do more with this data at some point, and this allows you to actually access the components of the data easily. Furthermore, it's comprehensible to a future maintainer since the reason behind the ordering is somewhat clear. By contrast, if you chose to do complex string-based processing it's often very hard to understand what's going on (especially if it's part of a larger program, and not a tiny example as here).
Making new types is cheap. If your method's return value doesn't quite "fit" in an existing type, just make a new one, even if that means 1000's of types.
A bit spoonfeeding, but I found this question pretty interesting and perhaps it will be useful for others, also added some comments to explain:
void Main()
{
var cardDatabase = new List<string>{
"MW1E10",
"MWSTX2FFI06",
"FWQ02",
"MW1Q04",
"MW1Q05",
"FWI01",
"MWSTX2FFA01",
"DNC03",
"MWSTX1CKC02",
"MWSTX2FFI03",
"MW1I06",
};
var orderTable = new List<string>[]{
new List<string>
{
"MW1",
"FW",
"DN",
"MWSTX1CK",
"MWSTX2FF"
},
new List<string>
{
"Q",
"J",
"C",
"E",
"I",
"A"
}
};
var test = cardDatabase.Select(input => {
var r = Regex.Match(input, "^(MW1|FW|DN|MWSTX1CK|MWSTX2FF)(A|Q|J|C|E|I|A)([0-9]+)$");
if(!r.Success) throw new Exception("Invalid data!");
// for each input string,
// we are going to split it into "substrings",
// eg: MWSTX1CKC02 will be
// [MWSTX1CK, C, 02]
// after that, we use IndexOf on each component
// to calculate "real" order,
// note that thirdComponent(aka number component)
// does not need IndexOf because it is already representing the real order,
// we still want to convert string to integer though, because we don't like
// "string ordering" for numbers.
return new
{
input = input,
firstComponent = orderTable[0].IndexOf(r.Groups[1].Value),
secondComponent = orderTable[1].IndexOf(r.Groups[2].Value),
thirdComponent = int.Parse(r.Groups[3].Value)
};
// and after it's done,
// we start using LINQ OrderBy and ThenBy functions
// to have our custom sorting.
})
.OrderBy(calculatedInput => calculatedInput.firstComponent)
.ThenBy(calculatedInput => calculatedInput.secondComponent)
.ThenBy(calculatedInput => calculatedInput.thirdComponent)
.Select(calculatedInput => calculatedInput.input)
.ToList();
Console.WriteLine(test);
}
You can use the Array.Sort() method. Where your first parameter is the string[] you're sorting and the second parameter contains the complicated logic of determining the order.
You can use the IEnumerable.OrderBy method provided by the System.Linq namespace.
Does NUnit provide a constraint to find whether the actual value is the element of a given enumerable or array, in other words, that it is equal to any of multiple expected values? Something like:
Assert.That(actual, Is.EqualToAnyOf(new[] { 1, 2, 3 }))
That is, to point out, the actual is a single value. I expect the value to be either 1, 2, or 3. The assertion
Assert.That(actual, Contains.Element(expected))
checks logically the same, but it is the opposite intention: Here we have a collection of actual values and expect one value to be in it.
Furthermore, I found these but they all don't fit:
Assert.That(actual, Is.EqualTo(expected)) // only allows one value
Assert.That(actual, Is.InRange(start, end)) // only works for consecutive numbers
Assert.That(actual, Is.SubsetOf(expected)) // only works if actual is an enumerable
Assert.That(expected.Contains(actual)) // meaningless "expected: true but was: false" message
CollectionAssert should be what you need if I am not overlooking something. It is as simple as:
CollectionAssert.Contains(IEnumerable expected, object actual);
However, there seems to be several ways to achieve your goal, such as:
[Test]
public void CollectionContains()
{
var expected = new List<int> { 0, 1, 2, 3, 5 };
var actual = 5;
CollectionAssert.Contains(expected, actual);
Assert.That(expected, Contains.Item(actual));
}
Above assertions should basically assert the same and could be used interchangeably.
Edit:
Question was modified, stating that Assert.That(expected, Contains.Item(actual)); is not valid even though it logically tests the same thing.
There is a way to do this built in to NUnit, using the Or constraint:
Assert.That(actual, Is.EqualTo(1).Or.EqualTo(2).Or.EqualTo(3))
If your list is more dynamic, you can build your list of Ors like this:
var expected = new[] { 1, 2, 3 };
var constraints = Is.EqualTo(expected[0]);
for(var i = 1; i < expected.Length; i++)
constraints = constraints.Or.EqualTo(expected[i]);
Assert.That(actual, constraints);
That latter answer doesn't read as well in the fluid syntax, but does achieve the dynamic building of or constraints. You could probably wrap that in a custom constraint as patrick-quirk demonstrated in order to achieve a more readbale fluid syntax, but that's up to you.
I know this is an old question, bu I have a maybe better (and native) suggestion.
With NUnit 3.x (I'm on 3.10.1) you can use Is.AnyOf:
Assert.That(
actualValue,
Is.AnyOf(expectedValue1, expectedValue2, expectedValue3),
"My error message");
The only way I could see to accomplish this is by creating your own constraint. It's pretty straightforward to do though.
The constraint class itself:
public class OneOfValuesConstraint : EqualConstraint
{
readonly ICollection expected;
NUnitEqualityComparer comparer = new NUnitEqualityComparer();
public OneOfValuesConstraint(ICollection expected)
: base(expected)
{
this.expected = expected;
}
public override bool Matches(object actual)
{
// set the base class value so it appears in the error message
this.actual = actual;
Tolerance tolerance = Tolerance.Empty;
// Loop through the expected values and return true on first match
foreach (object value in expected)
if (comparer.AreEqual(value, actual, ref tolerance))
return true;
// No matches, return false
return false;
}
// Overridden for a cleaner error message (contributed by #chiccodoro)
public override void WriteMessageTo(MessageWriter writer)
{
writer.DisplayDifferences(this);
}
public override void WriteDescriptionTo(MessageWriter writer)
{
writer.Write("either of ");
writer.WriteExpectedValue(this.expected);
}
}
And to make it fluent, create a static method to wrap it (contributed by #chicodorro):
public static class IsEqual
{
public static OneOfValuesConstraint ToAny(ICollection expected)
{
return new OneOfValuesConstraint(expected);
}
}
Then to use it:
int[] expectedValues = new[] { 0, 1, 2 };
Assert.That(6, IsEqual.ToAny(expectedValues));
Fails with the message:
Expected: either of < 0, 1, 2 >
But was: 6