Glinkot
Glinkot

Reputation: 2974

C#: projection - accessing a given string property in a collection of objects in the same way as a List<string>

a quick projection question. I have a collection of objects (unchangeditems) in a test method, and would like to ensure they match my 'expected' elements. As shown you could do it by element, but this isn't ideal. I'm sure its possible to use projection to get down to the string variable (LMAA_CODE - don't ask about the capitals!) along the lines of the bottom line below. I'd appreciate a hand.

Thanks!

// Works but not very elegant
            Assert.AreEqual(result.unchangedItems[0].LMAA_CODE,expectedunchangedItems[0]);
            Assert.AreEqual(result.unchangedItems[1].LMAA_CODE,expectedunchangedItems[1]);
            Assert.AreEqual(result.unchangedItems[2].LMAA_CODE,expectedunchangedItems[2]);
            Assert.AreEqual(result.unchangedItems[3].LMAA_CODE,expectedunchangedItems[3]);

        // ?Can something like this be done?  eg result.unchangedItems => result.unchangedItems.LMAA_CODE
        Assert.IsTrue(Enumerable.SequenceEqual(result.unchangedItems.LMAA_CODE, expectedunchangedItems));

Upvotes: 2

Views: 307

Answers (4)

Qwertie
Qwertie

Reputation: 17196

You could also use a "Zip" extension method.

Assert.AreEqual(result.unchangedItems.Count, expectedunchangedItems.Count);
result.unchangedItems.Zip(expectedunchangedItems, (a, b) => Tuple.Create(a, b))
                     .ForEach(p => Assert.AreEqual(p.Item1.LMAA_CODE, p.Item2));

This way, the exception reports which value was not expected. The Zip() method is included in .NET 4, but I personally prefer to use my own, and of course you'd want a ForEach() too:

// I actually have a Pair<A,B> struct that I prefer to use, but 
// KeyValuePair or Tuple works almost as well.
public static IEnumerable<Tuple<A, B>> ZipTuples<A, B>(this IEnumerable<A> a, IEnumerable<B> b)
{
    IEnumerator<A> ea = a.GetEnumerator();
    IEnumerator<B> eb = b.GetEnumerator();
    while (ea.MoveNext() && eb.MoveNext())
        yield return new Tuple<A, B>(ea.Current, eb.Current);
}
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
    foreach (T item in list)
        action(item);
}

Usage:

Assert.AreEqual(result.unchangedItems.Count, expectedunchangedItems.Count);
result.unchangedItems.ZipTuples(expectedunchangedItems)
                     .ForEach(p => Assert.AreEqual(p.Item1.LMAA_CODE, p.Item2));

Upvotes: 0

Oscar Mederos
Oscar Mederos

Reputation: 29863

What about:

for (int i = 0; i < result.unchangedItems.Count; i++) {
    Assert.AreEqual(result.unchangedItems[i].LMAA_CODE, expectedUnchangedItems[i]);
}

You can also do:

Assert.IsFalse(result.unchangedItems.Where((r,i) => expectedUnchangedItems[i] != r.LMAA_CODE).Any())

.Any() will return true if the filtered sequence contains elements, and it shouldn't. That's why you call IsFalse. If your testing framework (or whatever you are using) does not have that, you can always do Assert.AreEqual(____, false).

Upvotes: 1

BrokenGlass
BrokenGlass

Reputation: 160952

You were almost there already, just added a projection to LMAA_CODE:

 Assert.IsTrue(Enumerable.SequenceEqual(result.unchangedItems.Select( x=> x.LMAA_CODE), 
                                        expectedunchangedItems));

Upvotes: 4

Rick Sladkey
Rick Sladkey

Reputation: 34250

You can use LINQ and Zip:

Assert.IsTrue(result.unchangedItems.Zip(expectedunchangedItems, (actual, expected) => actual.LMAA_CODE == expected).All(value => value));

Upvotes: 1

Related Questions