I want to be able to compare the two following objects for likeness using AutoFixture.SemanticComparison:
public class Object1
{
public int a;
}
public class Object2
{
public int a;
public int b;
}
Now, when I do it this way:
var o1 = new Object1 { a = 1 };
var o2 = new Object2 { a = 1, b = 2};
o1.AsSource().OfLikeness<Object2>().ShouldEqual(o2);
I get the following exception: "The following members did not match: - b."
I found out that I can omit the 'b' member like this:
var o1 = new Object1 { a = 1 };
var o2 = new Object2 { a = 1, b = 2};
o1.AsSource().OfLikeness<Object2>().Without(object2 => object2.b).ShouldEqual(o2);
However, I find that this is quite cumbersome, because whenever I add a new member to class Object2, I have to correct my unit tests (or at least unit test helpers).
Is there a way to say "I want to compare for likeness just for the subset that exists in both objects"?
It sounds like you'd like to compare two objects based on the intersection of their properties. This is not currently supported by the Likeness class. The reasoning is this:
Right now the destination type (in the above example, that would be Object2) is the decisive template upon which matching is done. This provides quite a strong statement for an assertion: every public property or field of this class must be matched.
However, a statement about matching the intersection of properties would be a very weak statement, because that intersection might be empty. This could result in False Negatives.
Even if you are TDDing and following the Red/Green/Refactor cycle and you've seen a unit test failing with such a hypothetical Likeness intersection, subsequent refactorings might turn such an assertion into a False Negative, as you remove the last property or field the two objects have in common - and you'll never notice.
However, AutoFixture is open source and all, so you're welcome to suggest this feature or send a pull request.
Related
I am attempting to iterate through the members of a list which implement a particular interface, called ImplementsGraphics and then call the method GetModels and add the return result to a list.
However, whenever I attempt to iterate through my objects, and perform the casting operation, I appear to be overwriting the same reference during my iteration. I have deduced that my problem is something to do with where, when and how I am instantiating my variables, but I can not decipher exactly what the intended behavior is.
I've tried numerous permutations of the following code:
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors.Where(n=>n is ImplementsGraphics))
{
var graphicActor = (ImplementsGraphics)actor;
models.AddRange(graphicActor.GetModels());
}
return models;
}
The problem line is var graphicActor = (ImplementsGraphics)actor; but I don't know how to write it such that declaring graphicsActor does not overwrite the existing instances of it stored in models.
Before my first several rounds of troubleshooting, I had
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors)
{
if((ImplementsGraphics)actor != null)
models.AddRange(((ImplementsGraphics)actor).GetModels());
}
return models;
}
Which I expected to work, as I had thought actor was safe across iteration, but apparently not.
Desired Behavior:
Return a list, which is all the return results of GetModels() for ever Actor in RegisteredActors which implements ImplementsGraphics
Actual Behavior:
Returns a list, which is the same return value repeated for each Actor in Registered Actor, which implements ImplementsGraphics.
EDIT:
In the class StaticActor which is a child of Actor and implements ImplementsGraphics its defined as follows:
public List<Model> GetModels()
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = this.Transform.WorldMatrix;
}
}
return new List<Model> { Model };
}
Additonally, I have tried two other approaches which also failed. A for loop, which itereated through all of RegisteredActors, and checked if they implemented ImplementsGraphics, explicitly calling them by their index within RegisteredActors
And a LINQ query, which went
var models = RegisteredActors.Where(n=>n is ImplementsGraphics).SelectMany(n=>((ImplementsGraphics)n).GetModels())
EDIT 2:
The deinfitions of my classes are largely irrelevant, if you want a reproducable example of the behaviour I'm having trouble with, here is a far simpler example.
class MyClass
{
MyOtherClass foo = new MyOtherClass();
int bar = 0;
MyOtherClass GetOtherClass()
{
foo.bar = bar;
return foo;
}
}
class MyOtherClass
{
int bar = 0;
}
List<MyClass> MyCollection = new List<MyClass> {new MyClass(bar = 1), new MyClass(bar = 2), new Myclass(bar = 3)};
List<MyOtherClass> MyOtherCollection = new List<MyOtherClass>();
foreach(MyClass member in MyCollection)
{
MyOtherCollection.Add(member.GetOtherClass());
}
If you were to execute the above code, I expect that the value of MyOtherCollection's bar properties would be: 1, 2, 3
However, the actual result is that:
During the first iteration the values are 1
During the second iteration the values are 2, 2
During the third iteration the values are 3, 3, 3
I would appear, since none of the provided code states, only implies, that you are attempting to reuse a reference to single Model instance to draw multiple objects. Then you are adding multiple references of the same instance to the List.
The solution may be as simple as removing the static modifier from all Model variables and/or container objects.
Normally, the solution would be to create a Deep Copy of the object when it is added to the List, however, it is not directly possible to do this in XNA *1. (not that you would want to)
It would be better to allow each Actor, or StaticActor, object to directly pass its own Model(s) through the GetModels() method in the interface implementation, instead of using the additional class MyOtherClass.
*1. XNA does not expose a public constructor for the Model class. It is possible to do this using reflection. In MonoGame, there is a public Constructor available.
I tend to split my derived Classes and subsequent Lists based on properties like "StaticCollidables","DrawableStaticCollidables" and "DrawableMovingCollidables"...
This technique may require more upfront coding(and therefore is not as "elegant"), but, it is more efficient in terms of memory overhead(8 bytes + (4(32 bit) or 8(64 bit) bytes depending on sizeof(Object)) per List) and CPU overhead(no casting or is).
If you are attempting to reuse the same model, but place it in different locations, use the DrawInstancedPrimitives method using the VertexBuffers contained within each Mesh of the model.
Please comment on which of the above solutions worked for you(if any). If I have missed something please let me know, so I can correct the answer.
I thought I had a good understanding of the anonymous type, but this small code snippet has left me a little confused:
string[] arr = { "Agnes", "Allan", "Benny" };
var result = arr.Where(a => a.StartsWith("A")).Select(a => a);
// Why can I do the below, if arr is immutable?
result = arr.Where(a => a.EndsWith("n")).Select(a => a);
What I don't understand is why I am allowed to assign a second value to result. I mean isn't the idea of anonymous types being immutable, that they cannot be changed after they have got their initial value?
First, there is no anonymous type involved.
This string[] arr = { "Agnes", "Allan", "Benny" }; is an array creation expression.
result is IEnumerable<string> and in both LINQ statements you are just creating a query.
This is what is going on:
array creation expression
string[] arr = { "Agnes", "Allan", "Benny" };
query arr and returns IEnumerable<string>
var result = arr.Where(a => a.StartsWith("A")).Select(a => a);
assigns results a new query on arr returning IEnumerable<string>
result = arr.Where(a => a.EndsWith("n")).Select(a => a);
As far as, for understanding immutability, think of String also see this article: Immutable types: understand their benefits and use them
You have an anonymous type when you do something like:
var anon = new { X = 5, Y = 6 };
There are some pretty simple rules: you can't express the type of an anonymous type (so often you use var)... there must be a new {... You must give a name to the properties and a value X = 5.
What you are doing is creating an array of string[] using an array initializer. You are even writing it:
string[] arr = ...
And you aren't modifying anything... result is another variable, referencing an IEnumerable<> (a new object you are creating) and then referencing another IEnumerable<> At the end of your code you have 6 objects (a little more, but we will ignore some invisible objects):
The array referenced by arr (and referenced by the two IEnumerable<>)
The second IEnumerable<>, referenced by result, that has a reference to arr
The first IEnumerable<>, not referenced by anyone (the GC will collect it before or later), that has a reference to arr
3x string, all referenced by arr. Note that IEnumerable<> are "lazy", so they don't contain any reference to any string
The result variable is assigned twice, to two different IEnumerable<>. It is nearly always legal to reassign variables (exception are readonly fields). it is clearly legal to do:
string foo = "Foo";
foo = "Bar";
Another useful concept to understand is the difference between type, instance and variable.
Simplifying, type is like a blueprint, it describes what an instance of the type will look like:
class Car
{
public int Doors {get; set;}
public string EngineType { get; set;}
}
The code above describes type. You can make many instances of this type:
Car truck = new Car { Doors = 2, EngineType = "BigEckingEngine" };
Car pickup = new Car { Doors = 5, Engine Type = "4 cylinder" };
etc...
Note how variables truck and pickup house your instances. But variables are just that, they can house any instance of their respective type, so while it does not make much sense you can do this:
Car tmp = truck;
truck = pickup;
pickup = tmp;
The instances themselves has not changed. But the variables now hold different instances.
The instances of this example Car class above are mutable. So you can do this:
pickup.Doors = 99;
Should the type be immutable, you would not be able to do that, but you are still can do variable assigning as in the example with the tmp variable freely, regardless of type being mutable or not, because such assignment do not change instances.
As noted, your example does not contain an anonymous type, but even if it did, it does not involve any kind of mutation you are asking about.
LINQ methods like Where() and Select() don't change the underlying array. It creates a new object. The created result is of type IEnumerable<string>, LINQ just filters the array so if you will iterate over it later, you will just get values that match Where and Select but your arr object will remain unchanged.
It's worth expanding the other answers to show that a CONCRETE resolution of a LINQ query is not the same as a IEnumerable<T> and that neither have anything to do with anonymous type immutability.
If you created the following array of anonymous types:
var arr = new[] { new { Name = "Agnes"}, new { Name = "Allan" }, new { Name = "Benny" }};
arr.GetType().Dump();
var result = arr.Where(a => a.Name.StartsWith("A")).Select(a => a)
result = arr.Where(a => a.Name.EndsWith("n")).Select(a => a);
result.Dump();
in my case,
<>f__AnonymousType0`1[System.String][]
and
"Allan"
are respectively outputted, because result type is actually
System.Linq.Enumerable+WhereSelectArrayIterator`2[
<>f__AnonymousType0`1[System.String],
<>f__AnonymousType0`1[System.String]]
In addition, if I try to resolve the IEnumerable and then re-update the result:
var result = arr.Where(a => a.Name.StartsWith("A")).Select(a => a).ToList();
result = arr.Where(a => a.Name.EndsWith("n")).Select(a => a).ToList();
I once again get an output of
"Allan"
However, in this case my result type has been reevaluated to
System.Collections.Generic.List`1[<>f__AnonymousType0`1[System.String]]
since ToList() is creating a new collection. I can technically add and remove to that collection at will since the collection itself is quite willing to be mutated.
Finally, that does not mean that the underlying anonymous type object is not immutable!
result.First ().Name = "fail";
Will fail, regardless of result being a list with the following error:
Property or indexer 'AnonymousType#1.Name' cannot be assigned to -- it
is read only
precisely because it is immutable.
Either using Nunit or Microsoft.VisualStudio.TestTools.UnitTesting. Right now my assertion fails.
[TestMethod]
public void GivenEmptyBoardExpectEmptyBoard()
{
var test = new Board();
var input = new Board()
{
Rows = new List<Row>()
{
new Row(){Cells = new List<int>(){0,0,0,0}},
new Row(){Cells = new List<int>(){0,0,0,0}},
new Row(){Cells = new List<int>(){0,0,0,0}},
new Row(){Cells = new List<int>(){0,0,0,0}},
}
};
var expected = new Board()
{
Rows = new List<Row>()
{
new Row(){Cells = new List<int>(){0,0,0,0}},
new Row(){Cells = new List<int>(){0,0,0,0}},
new Row(){Cells = new List<int>(){0,0,0,0}},
new Row(){Cells = new List<int>(){0,0,0,0}},
}
};
var lifeOrchestration = new LifeOrchestration();
var actual = lifeOrchestration.Evolve(input);
Assert.AreEqual(expected, actual);
}
You've got two different Board instances, so your call to Assert.AreEqual will fail. Even if their entire contents appear to be the same, you're comparing references, not the underlying values.
You have to specify what makes two Board instances equal.
You can do it in your test:
Assert.AreEqual(expected.Rows.Count, actual.Rows.Count);
Assert.AreEqual(expected.Rows[0].Cells[0], actual.Rows[0].Cells[0]);
// Lots more tests of equality...
Or you can do it in your classes: (note I wrote this on-the-fly - you'll want to adjust this)
public class Board
{
public List<Row> Rows = new List<Row>();
public override bool Equals(object obj)
{
var board = obj as Board;
if (board == null)
return false;
if (board.Rows.Count != Rows.Count)
return false;
return !board.Rows.Where((t, i) => !t.Equals(Rows[i])).Any();
}
public override int GetHashCode()
{
// determine what's appropriate to return here - a unique board id may be appropriate if available
}
}
public class Row
{
public List<int> Cells = new List<int>();
public override bool Equals(object obj)
{
var row = obj as Row;
if (row == null)
return false;
if (row.Cells.Count != Cells.Count)
return false;
if (row.Cells.Except(Cells).Any())
return false;
return true;
}
public override int GetHashCode()
{
// determine what's appropriate to return here - a unique row id may be appropriate if available
}
}
I used to override getHasCode and equals, but I never liked it since I don't want to change my production code for the sake of unit testing.
Also it's kind of pain.
Then I turned too reflection to compare objects which was less invasive...but that's kind of lot of work (lots of corner cases)
In the end I use:
http://www.nuget.org/packages/DeepEqual/
Works great.
Update, 6 years later:
I now use the more general library fluentassertions for .NET
it does the same as above but with more features and a nice DSL, the specific replacement would be: https://fluentassertions.com/objectgraphs/
PM> Install-Package FluentAssertions
Also after some years of experience, I still not recommend the override route, I'd even consider it a bad practice. If you're not careful you could introduce performance issues when using some Collections like Dictionaries. Also when the time would come where you will have a real business case to overload these methods you'd be in trouble because you'd have this test code in there already. Production code and test code should be kept separated, test code should not rely on implementation details or hacks to achieve their goal, this make them hard to maintain and understand.
For trivial objects, like domain objects or DTOs or entities, you could simply serialize both instances to a string and compare that string:
var object1Json = JsonConvert.SerializeObject(object1);
var object2Json = JsonConvert.SerializeObject(object2);
Assert.AreEqual(object1Json, object2Json);
This of course has various caveats, so evaluate whether for your classes, the JSON contains the expected values that should be compared.
For example, if your class contains unmanaged resources or otherwise not serializable properties, those won't be properly compared. It also only serializes public properties by default.
ExpectedObjects would help you to compare equality by property value. It supports:
simple object: expected.ToExpectedObject().ShouldEqual(actual);
collection: expected.ToExpectedObject().ShouldEqual(actual);
composized object: expected.ToExpectedObject().ShouldEqual(actual);
partial compare: expected object need design with anonymous type, and use expected.ToExpectedObject().ShouldMatch(actual)
I love ExpectedObjects because of I only need to invoke 2 API for assertion of comparing object equality:
ShouldEqual()
ShouldMatch() for partial comparing
I wanted a solution that didn't require adding a dependency, worked with VS unit tests, compared the field values of two objects,and told me all unequal fields. This is what I came up with. Note it could be extended to work with property values as well.
In my case, this works well for comparing the results of some file-parsing logic to ensure two technically "different" entries have fields with the same values.
public class AssertHelper
{
public static void HasEqualFieldValues<T>(T expected, T actual)
{
var failures = new List<string>();
var fields = typeof(T).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
foreach(var field in fields)
{
var v1 = field.GetValue(expected);
var v2 = field.GetValue(actual);
if (v1 == null && v2 == null) continue;
if(!v1.Equals(v2)) failures.Add(string.Format("{0}: Expected:<{1}> Actual:<{2}>", field.Name, v1, v2));
}
if (failures.Any())
Assert.Fail("AssertHelper.HasEqualFieldValues failed. " + Environment.NewLine+ string.Join(Environment.NewLine, failures));
}
}
[TestClass]
public class AssertHelperTests
{
[TestMethod]
[ExpectedException(typeof(AssertFailedException))]
public void ShouldFailForDifferentClasses()
{
var actual = new NewPaymentEntry() { acct = "1" };
var expected = new NewPaymentEntry() { acct = "2" };
AssertHelper.HasEqualFieldValues(expected, actual);
}
}
Since neither have yet been mentioned on this question, there are a couple of other well adopted libraries out there that can help with this problem:
Fluent Assertions - see object graph comparison
actual.Should().BeEquivalentTo(expected);
Semantic Comparison
Likeness<MyModel, MyModel>(actual).ShouldEqual(expected);
I personally prefer Fluent Assertions as provides greater flexibility with member exclusions etc and it supports the comparison of nested objects out of the box.
Hope this helps!
Assert methods rely on the object's Equals and GetHashcode. You can implement that, but if this object equality is not needed outside unit tests I would instead consider comparing the individual primitive types on the object.
Looks like the objects are simple enough and overriding of equals is not really warranted.
If you want to compare only properties of a complex type object,
Iterating over object properties will gives all the properties.
You can try below code.
//Assert
foreach(PropertyInfo property in Object1.GetType().GetProperties())
{
Assert.AreEqual(property.GetValue(Object1), property.GetValue(Object2));
}
I've considered 2 cases:
var a = new { a = 5 };
var b = new { a = 6 };
Console.WriteLine(a.GetType() == b.GetType()); // True
Ideone: http://ideone.com/F8QwHY
and:
var a = new { a = 5, b = 7 };
var b = new { b = 7, a = 6 };
Console.WriteLine(a.GetType() == b.GetType()); // False
Ideone: http://ideone.com/hDTcxX
The question is why does order of fields actually matter?
Is there any reason for this or it's just simply because it is (such is the design).
If the reason is just that anonymus types are not supposed to be used this way and you are not supposed to appeal to GetType, then why does compiler re-use a single class in first case and not just generate a new class for each anonymus type declaration?
So the reason for the design decision was ToString. An anonymous type returns a different string accoding to the order. Read Eric Lippert's blog.
{ a = 5, b = 7 }
{ b = 7, a = 6 }
Demo
C# language specification, section 7.6.10.6, requires the sequence of properties to be the same in order for the anonymous types to be considered identical:
Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and compile-time types in the same order will produce instances of the same anonymous type.
In your second example, the first anonymous class has the sequence of properties {a, b}, while the second anonymous class has the sequence {b, a}. These sequences are not considered to be the same.
You lead on to what I'm guessing the reason is: the types are anonymous so depending on GetType() to return reliable results is a terrible idea.
As for why the compiler re-uses a type if the order matches, I'm guessing it's simply to save time and space. When you take order into account, it's far easier to cache generated classes during compilation and then re-use them when needed.
This is probably a basic question for some, but it affects how I design a piece of my program.
I have a single collection of type A:
IEnumerable<A> myCollection;
I am filtering my collection on 2 different criteria:
IEnumerable<A> subCollection1 = myCollection.Where(x => x.Count > 10);
etc.
Now, I know that the .Where expression will return a new instance of IEnumerable, but does the new collection contain the same reference to an instance of type A that 'myCollection' references, or are new copies of type A created? If new instances of type 'A' are created, is there a way to say that 'subCollection1' references the same instances of A as 'myCollection' references?
Edit: To Add further clarification.
I am looking for a way so that when I make a change to an instance of 'A' in 'subCollection1', that it is also modified for 'myCollection'.
The instances are the same if they are classes, but copies if they are structs/value types.
int, byte and double are value types, as are structs (like System.Drawing.Point and self-defined structs).
But strings, all of your own classes, basically "the rest", are reference types.
Note: LINQ uses the same rules as all other assignments.
For objects:
Person p1 = new Person();
p1.Name = "Mr Jones";
Person p2 = p1;
p2.Name = "Mr Anderssen";
// Now p1.Name is also "Mr Anderssen"
For structs:
Point p1 = new Point();
p1.x = 5;
Point p2 = p1;
p2.x = 10;
// p1.x is still 5
The same rules apply when using LINQ.
Actually it depends on the collection. In some cases, LINQ methods can return cloned objects instead of references to originals. Take a look at this test:
[Test]
public void Test_weird_linq()
{
var names = new[]{ "Fred", "Roman" };
var list = names.Select(x => new MyClass() { Name = x });
list.First().Name = "Craig";
Assert.AreEqual("Craig", list.First().Name);
}
public class MyClass
{
public string Name { get; set; }
}
This test will fail, even though many people believe that the same object will be returned by list.First(). It will work if you use another collection "modified with ToList()".
var list = names.Select(x => new MyClass() { Name = x }).ToList();
I don't know for sure why it works this way, but it's something to have in mind when you write your code :)
This question can help you understand how LINQ works internally.
They are same objects. Where only filters, Select produces (can produce) new instances.
Making a new object that is a reference type is non-trivial. LINQ would have no idea how to do it. LINQ always returns the same instances when dealing with reference types.
I just wanted to add to some of the other answers -- in general, when I'm not sure of something but require a particular behavior, I'll add a unit test for it. You could easily put this into a test and then check for equality, which will tell you if you're looking at a reference of the object in the original container. Some may argue that this is stupid because you "should just know" what happens, but for me I know I will either be 1) unsure because I'm not an awesome programmer, and 2) there are always nights where I have to burn the midnight oil, and it's good to have the reassurance that something behaves as you need it to.