Lambda expression as inline data in xUnit - c#

I'm pretty new to xUnit and here's what I'd like to achieve:
[Theory]
[InlineData((Config y) => y.Param1)]
[InlineData((Config y) => y.Param2)]
public void HasConfiguration(Func<Config, string> item)
{
var configuration = serviceProvider.GetService<GenericConfig>();
var x = item(configuration.Config1); // Config1 is of type Config
Assert.True(!string.IsNullOrEmpty(x));
}
Basically, I have a GenericConfig object which contains Config and other kind of configurations, but I need to check that every single parameter is valid. Since they're all string, I wanted to simplify using [InlineData] attribute instead of writing N equals tests.
Unfortunately the error I'm getting is "Cannot convert lambda expression to type 'object[]' because it's not a delegate type", which is pretty much clear.
Do you have any idea on how to overcome this?

In addition to the already posted answers. The test cases can be simplified by directly yielding the lambdas.
public class ConfigTestDataProvider
{
public static IEnumerable<object[]> TestCases
{
get
{
yield return new object [] { (Func<Config, object>)((x) => x.Param1) };
yield return new object [] { (Func<Config, object>)((x) => x.Param2) };
}
}
}
This test ConfigTestDataProvider can then directly inject the lambdas.
[Theory]
[MemberData(nameof(ConfigTestCase.TestCases), MemberType = typeof(ConfigTestCase))]
public void Test(Func<Config, object> func)
{
var config = serviceProvider.GetService<GenericConfig>();
var result = func(config.Config1);
Assert.True(!string.IsNullOrEmpty(result));
}

Actually, I was able to find a solution which is a bit better than the one provided by Iqon (thank you!).
Apparently, the InlineData attribute only supports primitive data types. If you need more complex types, you can use the MemberData attribute to feed the unit test with data from a custom data provider.
Here's how I solved the problem:
public class ConfigTestCase
{
public static readonly IReadOnlyDictionary<string, Func<Config, string>> testCases = new Dictionary<string, Func<Config, string>>
{
{ nameof(Config.Param1), (Config x) => x.Param1 },
{ nameof(Config.Param2), (Config x) => x.Param2 }
}
.ToImmutableDictionary();
public static IEnumerable<object[]> TestCases
{
get
{
var items = new List<object[]>();
foreach (var item in testCases)
items.Add(new object[] { item.Key });
return items;
}
}
}
And here's the test method:
[Theory]
[MemberData(nameof(ConfigTestCase.TestCases), MemberType = typeof(ConfigTestCase))]
public void Test(string currentField)
{
var func = ConfigTestCase.testCases.FirstOrDefault(x => x.Key == currentField).Value;
var config = serviceProvider.GetService<GenericConfig>();
var result = func(config.Config1);
Assert.True(!string.IsNullOrEmpty(result));
}
I could maybe come up with something a bit better or cleaner, but for now it works and the code is not duplicated.

I have the problem the same to you, and I found the solution that using TheoryData class and MemberData attribute. Here is the example and I hope the code usefully:
public class FooServiceTest
{
private IFooService _fooService;
private Mock<IFooRepository> _fooRepository;
//dummy data expression
//first parameter is expression
//second parameter is expected
public static TheoryData<Expression<Func<Foo, bool>>, object> dataExpression = new TheoryData<Expression<Func<Foo, bool>>, object>()
{
{ (p) => p.FooName == "Helios", "Helios" },
{ (p) => p.FooDescription == "Helios" && p.FooId == 1, "Helios" },
{ (p) => p.FooId == 2, "Poseidon" },
};
//dummy data source
public static List<Foo> DataTest = new List<Foo>
{
new Foo() { FooId = 1, FooName = "Helios", FooDescription = "Helios Description" },
new Foo() { FooId = 2, FooName = "Poseidon", FooDescription = "Poseidon Description" },
};
//constructor
public FooServiceTest()
{
this._fooRepository = new Mock<IFooRepository>();
this._fooService = new FooService(this._fooRepository.Object);
}
[Theory]
[MemberData(nameof(dataExpression))]
public void Find_Test(Expression<Func<Foo, bool>> expression, object expected)
{
this._fooRepository.Setup(setup => setup.FindAsync(It.IsAny<Expression<Func<Foo, bool>>>()))
.ReturnsAsync(DataTest.Where(expression.Compile()));
var actual = this._fooService.FindAsync(expression).Result;
Assert.Equal(expected, actual.FooName);
}
}

Oddly delegates are not objects, but Actions or Funcs are. To do this, you have to cast the lambda to one of these types.
object o = (Func<Config, string>)((Config y) => y.Param1)
But doing this, your expression is not constant anymore. So this will prevent usage in an Attribute.
There is no way of passing lambdas as attributes.
One possible solution would be to use function calls, instead of attributes. Not as pretty, but could solve your problem without duplicate code:
private void HasConfiguration(Func<Config, string> item)
{
var configuration = serviceProvider.GetService<GenericConfig>();
var x = item(configuration.Config1); // Config1 is of type Config
Assert.True(!string.IsNullOrEmpty(x));
}
[Theory]
public Test1()
{
HasConfiguration((Config y) => y.Param1);
}
[Theory]
public Test2()
{
HasConfiguration((Config y) => y.Param2);
}

public class HrcpDbTests
{
[Theory]
[MemberData(nameof(TestData))]
public void Test(Expression<Func<bool>> exp)
{
// Arrange
// Act
// Assert
}
public static IEnumerable<object[]> TestData
{
get
{
Expression<Func<bool>> mockExp1 = () => 1 == 0;
Expression<Func<bool>> mockExp2 = () => 1 != 2;
return new List<object[]>
{
new object[]
{
mockExp1
},
new object[]
{
mockExp2
}
}
}
}
}

Related

Can you get a value in a structure through an outside variable in C#?

So, I am kind of used to structuring things like JavaScript and in light of that I do struggle in some areas in C#. Right now I'm trying to use structures in a way I can call a value using a variable that would match the value I'm going for.
For example my structure would be this:
public struct test
{
public int[] valuesOne;
public int[] valuesTwo;
public test(int[] data)
{
valuesOne = new int[2] { data[0], data[1] };
valuesTwo = new int[2] { data[2], data[3] };
}
}
Okay so say I have all of this and I want to get test.valuesOne[0] but from a variable like so:
string getValue = "valuesOne";
Console.Log(test[getValue][0]);
I know this provides a indexing error, but I'm in a situation where I kind of want this functionality. Sure I can pass my structure through a simple method, but if I can do it in a similar way to this without a huge problem I'd like to.
c# and JavaScript are two different pairs of shoes.
I try to do something similar as your code, however not sure if that's what you're looking for.
class Program
{
static void Main(string[] args)
{
var t = new Test(new int[] { 1, 2, 3, 4 });
var value = t["valueOne"][0];
Console.WriteLine(value);
}
}
public class Test
{
private Dictionary<string, int[]> _data = new Dictionary<string, int[]>();
public Test(int[] data)
{
_data.Add("valueOne", new int[] { data[0], data[1]});
_data.Add("valueTwo", new int[] { data[2], data[3]});
}
public int[] this [string value]
{
get { return _data[value]; }
}
}
you can use dynamic + reflection + this[string key] to do it. but it needs some extra code.
note :
it's a bad idea,this will lose the advantage of strong type checking.
demo :
void Main()
{
var test = new test(new[] {1,2,3,4,5});
Console.WriteLine( test["valuesOne"][0] ); //1
Console.WriteLine( test["valuesTwo"][1] ); //4
}
public struct test
{
public int[] valuesOne;
public int[] valuesTwo;
public test(int[] data)
{
valuesOne = new int[2] { data[0], data[1] };
valuesTwo = new int[2] { data[2], data[3] };
}
public dynamic this[string key]
{
get
{
return this.GetFieldValue(key);
}
}
}
public static class Extension
{
public static object GetFieldValue(this object t, string fieldName)
{
var type = t.GetType();
var fields = type.GetFields();
var field = fields.Single(pi => pi.Name == fieldName);
return field.GetValue(t);
}
}
online demo link : can-you-get-a-value-in-a-structure-through-an-outside-variable-in-c | .NET Fiddle
Usually I too would recommend using a Dictionary as in #gsharp's answer. But since that isn't an option for you, perhaps you could go with a Dictionary of delegates instead:
var accessor = new Dictionary<string, Func<test, int[]>>
{
{ nameof(test.valuesOne), x => x.valuesOne },
{ nameof(test.valuesTwo), x => x.valuesTwo }
};
Now you can access your data like so:
string getValue = "valuesOne";
Console.Log(accessor[getValue](test_instance)[0]);
You can extend this concept by wrapping this Dictionary into an Extension Method:
public static class Extensions
{
private static new Dictionary<string, Func<test, int[]>> accessor =
new Dictionary<string, Func<test, int[]>>
{
{ nameof(test.valuesOne), x => x.valuesOne },
{ nameof(test.valuesTwo), x => x.valuesTwo }
};
public static int[] Property(this test t, string name)
{
return accessor[name](t);
}
}
Then you can write:
Console.Log(test_instance.Property(getValue)[0]);

How to combine Expression<TDelegate> objects without invoking?

I have a delegate as follows:
public delegate TestResult TestCase(byte[] source);
...where the return TestResult is as follows:
public class TestResult {
public bool Pass { get; }
public int Index { get; }
public TestResult(bool result, int index) {
Pass = result;
Index = index;
}
}
An example TestCase delegate looks like:
public static TestResult In(byte[] tkn, ITestSet testSet) {
return testSet.Contains(tkn);
}
ITestSet is not much more than an encapsulated HashSet<byte[]>.
In one use case I have 2 test sets: (1) A - z, (2) 0 - 9. I want to test if an input byte[] is in either test set.
I am using Expression<TestCase> but having trouble figuring out how to implement the Or test case. I have a TestCaseBuilder with the following methods:
public class TestCaseBuilder {
private Expression<TestCase> tcExpr;
public TestCaseBuilder With(TestCaseBuilder tcBuilder) {
tcExpr = tcBuilder.tcExpr;
return this;
}
public TestCaseBuilder Or(TestCaseBuilder tcBuilder) {
tcExpr = tcExpr.Or(tcBuilder.tcExpr);
return this;
}
}
...and my extension method:
public static Expression<TestCase> Or (this Expression<TestCase> tcLeft, Expression<TestCase> tcRight) {
var lExpr = (LambdaExpression)tcLeft;
var rExpr = (LambdaExpression)tcRight;
var param = lExpr.Parameters;
return Expression.Lambda<TestCase>(/* what to do here ? */, param);
}
Expression.OrElse is mechanically what I would think is appropriate but cannot use that since I am returning a TestResult, not a bool.
Here is how the TestCaseBuilder is used:
testcaseBuilder.As("Foo")
.With(isLetterTestCase)
.Or(isDigitTestCase);
I have performed the Or using just the TestCase delegates:
public static TestCase Or(this TestCase tc1, TestCase tc2) {
return tkn => {
var res = tc1(tkn);
if (res.Pass) {
return res;
}
return tc2(tkn);
};
}
How can I combine the 2 Expression<TestCase> in a custom Or method without invoking the first test case?
Is this what you wanted
public static Expression<Func<byte[], TestResult, TestCase, TestResult>> helperExp = (inp, res, next) => res.Pass ? next(inp) : res;
public static Expression<TestCase> Or(Expression<TestCase> exp1, Expression<TestCase> exp2)
{
var param = exp1.Parameters;
Expression<TestCase> or = Expression.Lambda<TestCase>(
Expression.Invoke(helperExp,
param[0], Expression.Invoke(exp1, param), exp2),param);
return or;
}
With a block expression no invoke
public static Expression<TestCase> Or(Expression<TestCase> exp1, Expression<TestCase> exp2)
{
var param = exp1.Parameters;
ParameterExpression local = Expression.Parameter(typeof(TestResult), "local");
BlockExpression block = Expression.Block(
new[] { local },
Expression.Assign(local, exp1.Body),
Expression.Condition(Expression.Property(local, nameof(TestResult.Pass)), exp2.Body, local));
return Expression.Lambda<TestCase>(block, param);
}
Test
Expression<TestCase> exp1 = (tc) => new TestResult(true);
Expression<TestCase> exp2 = (tc) => new TestResult(false);
var first = Or(exp1, exp1);
var second = Or(first, exp2);
var func = second.Compile();
var result = func(new byte[] { });
There might be a better way to do a conditional monad without expressions using https://github.com/louthy/csharp-monad
I thing .net core uses the monad principle for middleware.

Unit Testing - Some difficulties mocking

I'm working with some legacy code which I require to write some unit tests for. There is data access method with the following signature.
Task ExecuteReaderAsync(string procedureName, Parameters procedureParameters,
params Action<System.Data.IDataReader>[] actions);
which there is an implementation in the class i'm testing similar to this
private async Task<CustomObject> GetCustomObject(int id)
{
CustomObject obj = null;
await db.ExecuteReaderAsync("nameOfProcedure", some parameters,
dr =>
{
obj = new CustomObject()
{
Prop1 = dr["Col1"],
Prop2 = dr["Col2"]
}
}
return obj;
}
What I'm struggling with is being able to control the values returned by GetCustomObject. If ExecuteReaderAsync actually returned something I could have a set up like this.
mockDataAccess.Setup(x => x.ExecuteReaderAsync("nameOfProcedure", It.IsAny<Parameters>()))
.Returns(Task.FromResult(new CustomeObject() { prop1 = "abc", prop2 = "def"};));
But the logic for specifying the values is an Action<IDataReader> which I don't control. I'm wondering if there are any tricks I could employ to do what I want,
i.e. control the value of the object returned by GetCustomObject.
Take a look at the following example
[TestClass]
public class LegacyCodeTest {
[TestMethod]
public async Task TestExecuteReaderAsync() {
//Arrange
var mapping = new Dictionary<string, string> {
{ "Col1", "abc" },
{ "Col2", "def" }
};
var mockDataReader = new Mock<IDataReader>();
mockDataReader
.Setup(m => m[It.IsAny<string>()])
.Returns<string>(col => mapping[col])
.Verifiable();
var mockDataAccess = new Mock<IDataAccess>();
mockDataAccess
.Setup(m => m.ExecuteReaderAsync("nameOfProcedure", It.IsAny<Parameters>(), It.IsAny<Action<System.Data.IDataReader>[]>()))
.Returns(Task.FromResult<object>(null))
.Callback((string s, Parameters p, Action<System.Data.IDataReader>[] a) => {
if (a != null && a.Length > 0) {
a.ToList().ForEach(callback => callback(mockDataReader.Object));
}
})
.Verifiable();
var sut = new SUT(mockDataAccess.Object);
//Act
var actual = await sut.MUT(2);
//Assert
mockDataAccess.Verify();
mockDataReader.Verify(m => m["Col1"]);
mockDataReader.Verify(m => m["Col2"]);
actual.Should()
.NotBeNull()
.And
.Match<CustomObject>(c => c.Prop1 == mapping["Col1"] && c.Prop2 == mapping["Col2"]);
}
public interface IDataAccess {
Task ExecuteReaderAsync(string procedureName, Parameters procedureParameters, params Action<System.Data.IDataReader>[] actions);
}
public class Parameters { }
public class CustomObject {
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class SUT {
IDataAccess db;
public SUT(IDataAccess dataAccess) {
this.db = dataAccess;
}
public async Task<CustomObject> MUT(int id) {
var result = await GetCustomObject(id);
return result;
}
private async Task<CustomObject> GetCustomObject(int id) {
CustomObject obj = null;
await db.ExecuteReaderAsync("nameOfProcedure", null,
dr => {
obj = new CustomObject() {
Prop1 = dr["Col1"],
Prop2 = dr["Col2"]
};
});
return obj;
}
}
}
Since you don't have control of the Action<IDataReader>, in this case the most that can be done is to make sure that the action does not fail. So that would mean passing an a mock reader that performs as expected for the action.
var mapping = new Dictionary<string, string> {
{ "Col1", "abc" },
{ "Col2", "def" }
};
var mockDataReader = new Mock<IDataReader>();
mockDataReader
.Setup(m => m[It.IsAny<string>()])
.Returns<string>(col => mapping[col])
.Verifiable();
by using the call back to get access to the passed in parameters
.Callback((string s, Parameters p, Action<System.Data.IDataReader>[] a) => {
if (a != null && a.Length > 0) {
a.ToList().ForEach(callback => callback(mockDataReader.Object));
}
})
the mocked reader can be passed to the actions called within the method under test.
This answer is tailored to the provided example in th OP so some modification may need to be made for it to apply to your specific scenario. This should be enough to get you going for situations like this.

How can I call a reflected Func<T, T> property using Expression Trees

I have a generic class with a lambda property defined as such:
public class Transformation<TProperty> : TransformationBase
{
public Func<TProperty, TProperty> Transform { get; private set; }
...
I'm trying to compile an Action that can call this Transform property (on a property of Foo). I don't know TProperty at compile-time. I've started with this:
private static Action<Foo> Compile(Transformation transformation)
{
var fooParameter = Expression.Parameter(typeof(Foo));
var changePropertyValue = Expression.Constant(transformation);
var transformProperty = Expression.Property(changePropertyValue, "Transform");
var transfromCall = Expression.Call(transformProperty, ?
}
How can I call/execute the transformProperty?
EDIT: Foo (which is known a compile time) has an untyped property Value which needs to be transformed using the Transform property of the Transformation:
public class Foo {
public object Value { get; set; }
}
So, hand-written as an example where TProperty is string it would be:
Foo foo = ... // coming from an external source
Transformation<string> tranformation = ... // coming from an external source
foo.Value = transformation.Transform((string)foo.Value);
Except that I don't know the exact type of the Transformation as it is defined in an external assembly. So, instead of string it could be int or something else. That's why I want to use Expression Trees to compile an Action for a given transformation, such that I can call:
Foo foo = ... // coming from an external source
TransformationBase transformation = ... // coming from an external source
Action<Foo> transform = Compile(transformation);
transform(foo); // should transform foo.Value using the Transform property of 'transformation'
Note: I made Transformation inherit from TransformationBase to clarify this discussion.
Your problems relate more to the lack of typing around your problem. Foo.Value is loosely typed, but your transform functions are strongly typed. Expression Trees are also strongly typed. Using them doesn't allow you to magically call code in a loosely typed manner.
The solution is either a lot of reflection, or some easy dynamic:
EDIT: I added CompileUntyped which uses ExpressionTrees.I also added CompileReflection, which uses Reflection without ExpressionTrees. I would recommend the one that uses dynamic. It is by far the easiest to read, hence the easiest to maintain.
class Program
{
static void Main(string[] args)
{
var testTransform = new Transformation<string>
{
Transform = s => s.ToUpper()
};
var a = Compile(testTransform);
var foo = new Foo
{
Value = "test"
};
a(foo);
//foo.Value is now TEST
}
public static Action<Foo> CompileReflection(TransformationBase transformation)
{
var f = transformation
.GetType()
.GetProperty("Transform")
.GetGetMethod()
.Invoke(transformation, null) as Delegate;
return foo => foo.Value = f.DynamicInvoke(foo.Value);
}
public static Action<Foo> Compile(TransformationBase transformation)
{
return new Action<Foo>(f =>
{
dynamic d = f.Value;
dynamic t = transformation;
f.Value = t.Transform(d);
});
}
public static Action<Foo> CompileUntyped(TransformationBase transformation)
{
var transformType = transformation.GetType();
var genericType = transformType.GetGenericArguments().First();
var fooParam = Expression.Parameter(typeof(Foo), "f");
var valueGetter = typeof(Foo).GetProperty("Value").GetGetMethod();
var valueSetter = typeof(Foo).GetProperty("Value").GetSetMethod();
var transformFuncMember = transformType.GetProperty("Transform").GetGetMethod();
//Equivalent to f => f.Value = transformation.Transform((T)f.Value)
//Where T is the generic type parameter of the Transformation, and f is of type Foo
var expression = Expression.Lambda<Action<Foo>>(
Expression.Call(
fooParam,
valueSetter,
Expression.Invoke(
Expression.Property(
Expression.Constant(transformation, transformType),
transformFuncMember
),
Expression.Convert(
Expression.Property(fooParam, valueGetter),
genericType
)
)
), fooParam
);
return expression.Compile();
}
}
public class TransformationBase { }
public class Transformation<TProperty> : TransformationBase
{
public Func<TProperty, TProperty> Transform { get; set; }
}
public class Foo
{
public object Value { get; set; }
}
Not sure what are you trying to do BUT if I understand your intentions - I do not see need for compiling Expressions:
private static Action<TProperty> Compile<TProperty>(Transformation<TProperty> transformation)
{
return new Action<TProperty>(p => transformation.Transform(p));
}
See an example, it should give you what you want.
void Main()
{
var dummyObject = new Dummy { Test = "Hello!" };
var propertyTransform = Create(dummyObject, "Test");
propertyTransform(dummyObject);
Console.WriteLine("Final transformation " + dummyObject.Test);
}
class Dummy {
public string Test { get; set; }
}
// Define other methods and classes here
public class Transformation<TProperty>
{
public Func<TProperty, TProperty> Transform { get; set; }
}
public static Action<TObj> Create<TObj>(TObj myObject, string property){
var prop = myObject
.GetType()
.GetProperty(property);
var val = prop.GetValue(myObject);
var transformation = Create((dynamic)val);
var transform = transformation.Transform;
return obj => {
var newValue = transform((dynamic)val);
prop.SetValue(myObject, newValue);
};
}
public static Transformation<TProperty> Create<TProperty>(TProperty property){
var transformation = new Transformation<TProperty>();
// just a dummy hijacking.
if(typeof(TProperty)==typeof(string)){
Func<string, string> test = input => "I am changed man!";
transformation.Transform = (dynamic)test;
}
return transformation;
}
Output:
Final transformation I am changed man!

Assert two different types of enumerations are equivalent

I have an NUnit unit test which I have two collections of different types which I want to assert are equivalent.
class A { public int x; }
class B { public string y; }
[Test]
public void MyUnitTest()
{
var a = GetABunchOfAs(); // returns IEnumerable<A>
var b = GetABunchOfBs(); // returns IEnumerable<B>
Assert.IsPrettySimilar(a, b, (argA, argB) => argA.ToString() == argB);
}
where Assert.IsPrettySimilar is defined like such
public static void IsPrettySimilar<T1, T2>(
IEnumerable<T1> left,
IEnumerable<T2> right,
Func<T1, T2, bool> predicate)
{
using (var leftEnumerator = left.GetEnumerator())
using (var rightEnumerator = right.GetEnumerator())
{
while (true)
{
var leftMoved = leftEnumerator.MoveNext();
if (leftMoved != rightEnumerator.MoveNext())
{
Assert.Fail("Enumerators not of equal size");
}
if (!leftMoved)
{
break;
}
var isMatch = predicate(leftEnumerator.Current,
rightEnumerator.Current);
Assert.IsTrue(isMatch);
}
}
}
My question is, is there a more idiomatic way of doing the above with the existing methods in NUnit? I already looked at CollectionAssert and there's nothing matching what I want to do.
My description of "equivalent" in this case is:
1) Collections must be of same size
2) Collections must be in same logical order
3) Some predicate must be used to determine equivalence between matching items.
Let's think what you are trying to test. You are not trying to test that objects from first sequence are same as objects from second sequence. They can be very different. So, word similar is very vague here. What you really trying to test here, is that some projection of first sequence is equal to other projection of second sequence. And NUnit already have such functionality:
CollectionAssert.AreEqual(bunchOfAs.Select(a => a.ToString()),
bunchOfBs.Select(b => b));
Thus you are projecting both sequences to get particular data, then you can give nice names for these two projections, which will make your test readable to others. You have some hidden business logic here, which does not have explanation in code - you don't explain why you making such projections. So, nice names of projection results will explain your intent. E.g:
var expectedNames = employees.Select(u => u.Login);
var actualNames = customers.Select(c => c.Name);
CollectionAssert.AreEqual(expectedNames, actualNames);
That is much cleaner for me than
Assert.IsPrettySimilar(employees, customers, (e, c) => u.Login == c.Name);
I know you looked into CollectionAssert, however, I have found a strategy like this very useful in my own tests.
Overriding ToString and Equals on the objects makes this test pass.
[TestFixture]
public class Class1
{
[Test]
public void MyUnitTest()
{
var a = GetABunchOfAs(); // returns IEnumerable<A>
var b = GetABunchOfBs(); // returns IEnumerable<B>
CollectionAssert.AreEqual(a, b.OrderBy(x => x.y));
}
public List<A> GetABunchOfAs()
{
return new List<A>
{
new A() {x = 1},
new A() {x = 2},
new A() {x = 3},
new A() {x = 4}
};
}
public List<B> GetABunchOfBs()
{
return new List<B>
{
new B() {y = "4"},
new B() {y = "1"},
new B() {y = "2"},
new B() {y = "3"},
};
}
}
public class A
{
public int x;
public override bool Equals(object obj)
{
return obj.ToString().Equals(x.ToString());
}
public override string ToString()
{
return x.ToString();
}
}
public class B
{
public string y;
public override string ToString()
{
return y;
}
public override bool Equals(object obj)
{
return obj.ToString().Equals(y);
}
}
I deliberately left GetABunchOfBs out of order, however the test still passes.
It looks like Sergey's answer is the one I'm looking for (which was to see whether NUnit already has a facility to do what I want). However, this is the solution I ended up with, which is closer to the implementation I want.
public static class EnumerableAssert
{
public static void AreEquivilent<TExpected, TActual>(IEnumerable<TExpected> expected, IEnumerable<TActual> actual, Func<TExpected, TActual, bool> predicate)
{
if (ReferenceEquals(expected, actual))
{
return;
}
using (var expectedEnumerator = expected.GetEnumerator())
using (var actualEnumerator = actual.GetEnumerator())
{
while (true)
{
var expectedMoved = expectedEnumerator.MoveNext();
if (expectedMoved != actualEnumerator.MoveNext())
{
Assert.Fail("Expected and Actual collections are of different size");
}
if (!expectedMoved)
{
return;
}
Assert.IsTrue(predicate(expectedEnumerator.Current, actualEnumerator.Current));
}
}
}
}

Categories