I have been having issues implementing the correct technique to mock out the Linq methods for an IEnumerable.
{
var qs = Substitute.For<IEnumerable<object>>();
qs.ElementAt(i).Returns(q);
qs.Count().Returns(i);
}
Which is meant to test a method, which contains both pulling an item out of the list at random or in a controlled fashion.
private IEnumerable<T> list;
async object Save(object obj, byte i = 0)
{
var random = new Random();
var index = i == 0 ? random.Next(0, list.Count()) : i;
return list.ElementAt(index);
}
Doing this results in:
at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Linq.Enumerable.ElementAt[TSource](IEnumerable`1 source, Int32 index)
at King.Azure.Unit.Test.Data.StorageQueueShardsTests.<Save>d__11.MoveNext() in C:\Users\jefkin\Documents\GitHub\King.Azure\King.Azure.Unit.Test\Data\StorageQueueShardsTests.cs:line 127
--- End of stack trace from previous location where exception was thrown ---
at NUnit.Framework.Internal.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult)
at NUnit.Framework.Internal.Commands.TestMethodCommand.RunAsyncTestMethod(TestExecutionContext context)
Result Message:
System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
The only methods that can be mocked are either interface methods or virtual methods from classes.
Since ElementAt is an extension method and not a IEnumerable<T> method, it can't be mocked.
The best way to test this would be to use a List<T> instead and setup the list accordingly and not using NSubstitute.
For example:
var qs = new List<object> {
obj1,
obj2,
obj3
};
var result = sut.Save(obj, i);
var expected = qs[i];
Assert.Equal(expected, result);
Related
I would be grateful for assistance with the following question.
I would like to evaluate one or more data series with Xunit.
For this I have programmed a simple example.
Read the data series 10,20,30,40,80 and add 1 with a working method testAddValue.
public class TestDataRow
{
[Theory]
[MemberData(nameof(DataRowValue))]
[MemberData(nameof(ExpectedDataRowValue))]
public void TestDataRow_Method(List<int> TestValue, List<int> ExpectedValue)
{
// Init Method
Method testAddValue = new Method();
// Loop
for (int i = 0; i < TestValue.Count; i++)
{
var actual = testAddValue.TestDataRow_AddValue(TestValue[i], 1);
Assert.Equal(TestValue[i], ExpectedValue[i]);
}
}
public static IEnumerable<object[]> DataRowValue()
{
var testRow = new List<List<int>>
{
// TestValue
new List<int>{ 10, 20, 30, 40, 80},
};
yield return new object[] { testRow };
}
public static IEnumerable<object[]> ExpectedDataRowValue()
{
var expectedtestRow = new List<List<int>>
{
// ExpectedValue
new List<int>{ 11, 21, 31, 41, 81},
};
yield return new object[] { expectedtestRow };
}
}
The compiler gives no error message.
When I run the test with TestDataRow_Method(List TestValue), I get the message:
Object of type 'System.Collections.Generic.List1[System.Collections.Generic.List1[System.Int32]]' cannot be converted to type 'System.Collections.Generic.List`1[System.Int32]'.
I don't understand this error message....
When I run the test with TestDataRow_Method(List TestValue, List ExpectedValue), I get the message that ExpectedValue is not present. This is surely a consequential error that should be taken care of by solving the above problem. For a better understanding of my approach, I am posting the full code.
What am I doing wrong?
First, a comment: you've assigned a value to actual but you never use it. Instead, you assert that TestValue[i] is equal to ExpectedValue[i] which I hardly believe is your real intention here.
Your test method expects two arguments, so the MemberData methods have to yield an array with two elements. The first array element would be the list of test values, the second array element would be the list of expected values. As programmed, each MemberData methods returns an array with one element (a single list), so there is nothing for the second parameter of your test method.
The MemberData are not executed in parallel, but rather sequentially one after the other, first each output from DataRowValue is given to the test method and it is executed, then each output from ExpectedDataRowValue. As programmed, they each only return a single list, so you effectively have two specific separate test cases here.
I think your intention might be more along these lines (since you didn't include your class Method, I made a guess about what the method might be doing):
using System;
using System.Collections.Generic;
using Xunit;
namespace SO74067556
{
public class Method
{
public int TestDataRow_AddValue(int a, int b)
{
return a + b;
}
}
public class TestDataRow
{
[Theory]
[MemberData(nameof(TestData))]
public void TestDataRow_Method(int TestValue, int ExpectedValue)
{
// Arrange
Method testAddValue = new Method();
// Act
var actual = testAddValue.TestDataRow_AddValue(TestValue, 1);
// Assert
Assert.Equal(actual, ExpectedValue);
}
public static IEnumerable<object[]> TestData()
{
var data = new List<Tuple<int, int>>()
{
// Test values
new Tuple<int, int>(10,11),
new Tuple<int, int>(20,21),
new Tuple<int, int>(30,31),
new Tuple<int, int>(40,41),
new Tuple<int, int>(80,81)
};
foreach (Tuple<int, int> item in data)
{
yield return new object[] { item.Item1, item.Item2 };
}
}
}
}
For simple integer data like this, however, you would be better served by using InlineData:
[Theory]
//[MemberData(nameof(TestData))]
[InlineData(10, 11)]
[InlineData(20, 21)]
[InlineData(30, 31)]
[InlineData(40, 41)]
[InlineData(80, 81)]
public void TestDataRow_Method(int TestValue, int ExpectedValue)
{
// Arrange
Method testAddValue = new Method();
// Act
var actual = testAddValue.TestDataRow_AddValue(TestValue, 1);
// Assert
Assert.Equal(actual, ExpectedValue);
}
This is not only has less code, it is also easier to understand and the individual test cases show up in the Test Explorer in Visual Studio.
I want to return list of typenames from the class ApplicaitonType but i recieve error
Error 1 Instance argument: cannot convert from 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable' C:\Users\sharaman\documents\visual studio 2010\Projects\IssueTracking\BAL_IssueTracking\AppQuery.cs 19 17 BAL_IssueTracking
Please provide your feed back on it...much appericated
public static List AppType()
{
List<ApplicationType> m = new List<ApplicationType>();
var context = new Dll_IssueTracking.IssuTrackingEntities();// Object context defined in Dll_IssuTracking DLL
var query = from c in context.ApplicationTypes//Query to find TypeNames
select new { c.TypeName };
//return query.ToList<ApplicationType>();
m = query.ToList<ApplicationType>();//Error here
return m;
}
Your query selects a sequence of an anonymous type:
select new { c.TypeName };
It's not clear how you're expecting to turn that anonymous type into an ApplicationType.
Given your data source name, I'd expect the method to be as simple as:
public static List<ApplicationType> AppType()
{
using (var context = new Dll_IssueTracking.IssuTrackingEntities())
{
return context.ApplicationTypes.ToList();
}
}
In particular, it's pointless to create an instance of List<ApplicationType> and then ignore it, as you currently do:
List<ApplicationType> m = new List<ApplicationType>();
...
m = query.ToList<ApplicationType>();
return m;
Why would you bother with the variable here, and why would you assign a value to it which you never use?
EDIT: From your comment:
Actually I need to return TypeNames from ApplicaitonType class and bind to Dropdownlist through this function
That suggests your method is declared inappropriately. Either you can return a List<ApplicationType> and specify TypeName as the display part in the data binding, or you can change your method to return a List<string> (assuming that's the type of TypeName):
public static List<string> GetApplicationTypeNames()
{
using (var context = new Dll_IssueTracking.IssuTrackingEntities())
{
return context.ApplicationTypes.Select(type => type.typeName)
.ToList();
}
}
try with this code
public static List<ApplicationType> AppType()
{
var context = new Dll_IssueTracking.IssuTrackingEntities();// Object context defined in Dll_IssuTracking DLL
var query = from c in context.ApplicationTypes//Query to find TypeNames
select new ApplicationType{TypeName = c.TypeName };
return query.ToList();
}
I need to pass in a "where" lambda expression that'll be used in a LINQ query inside a method. The problem is, I don't know what the where value will be compared against until I get into the method.
Now to explain further and clarify some of what I said above I'll come up with a bit of a contrived example.
Imagine I have a List<Products> and I need to narrow that list down to a single record using a productId property of the Products object. Normally I would do this:
var product = productList.Where(p=>p.productId == 123).FirstOrDefault();
Now take it a step further - I need to put the above logic into a method that isn't limited to a List<Products> but is instead a List<T> so ideally, I'd be calling it like this (and I know the below won't work, it's simply here to show what I am trying to achieve):
myMethod(productList, p => p.productId == X)
With the caveat being that X isn't known until I'm inside the method.
Finally, for what it's worth, I need to point out that my collection of data is an OData DataServiceQuery.
So, to re-summarize my question: I need to know how to construct a lambda "where" expression that I can pass into a method and how to use it against a collection of objects in a LINQ query.
myMethod(productList, p => p.productId == X) - you can emulate with this trick
static void myMethod<T>(List<T> list, Func<T,bool> predicate, ref int x)
{
x = 5;
var v = list.Where(predicate);
foreach (var i in v)
Console.Write(i);
Console.ReadLine();
}
static void Main(string[] args)
{
List<int> x = new List<int> { 1, 2, 3, 4, 5 };
int z = 0;
myMethod(x, p => p == z, ref z);
}
but not sure if it solves your problem in whole
For one, if you are going to query an IEnumerable<T>, you will need to ensure that your comparison will work in the first place. In that case you can make your objects implement an interface that guarantees that they will support the comparison.
Once you do that, your method can have a generic constraint that limits the input to those interfaces. At that point, your method can take a Func, which can be passed to the LINQ Where clause:
public interface Identifier
{
int Id { get; set; }
}
public class Product : Identifier
{
public int Id { get; set; }
//Other stuff
}
public T GetMatch<T>(IEnumerable<T> collection, Func<T, int, bool> predicate) where T : Identifier
{
int comparison = 5;
return collection.Where(item => predicate(item, comparison)).FirstOrDefault();
}
Which can be invoked like:
var match = GetMatch<Identifier>(collection, (x, y) => x.Id == y);
UPDATE:
I modified the above code to take in a comparison parameter
You could try to use the PredicateBuilder class from the free LinqKit library(tutorial).
You can then construct a predicate using
PredicateBuilder predicate = PredicateBuilder.True<T>();
predicate = PredicateBuilder.And(predicate, p=> p.product_id == X);
where X is of type T.
You can use this predicate in a where clause such as .Where(predicate) and return an IQueryable or return the predicate itself which would be of type Expression<Func<T, bool>>
I'd like to split a sequence in C# to a sequence of sequences using LINQ. I've done some investigation, and the closest SO article I've found that is slightly related is this.
However, this question only asks how to partition the original sequence based upon a constant value. I would like to partition my sequence based on an operation.
Specifically, I have a list of objects which contain a decimal property.
public class ExampleClass
{
public decimal TheValue { get; set; }
}
Let's say I have a sequence of ExampleClass, and the corresponding sequence of values of TheValue is:
{0,1,2,3,1,1,4,6,7,0,1,0,2,3,5,7,6,5,4,3,2,1}
I'd like to partition the original sequence into an IEnumerable<IEnumerable<ExampleClass>> with values of TheValue resembling:
{{0,1,2,3}, {1,1,4,6,7}, {0,1}, {0,2,3,5,7}, {6,5,4,3,2,1}}
I'm just lost on how this would be implemented. SO, can you help?
I have a seriously ugly solution right now, but have a "feeling" that LINQ will increase the elegance of my code.
Okay, I think we can do this...
public static IEnumerable<IEnumerable<TElement>>
PartitionMontonically<TElement, TKey>
(this IEnumerable<TElement> source,
Func<TElement, TKey> selector)
{
// TODO: Argument validation and custom comparisons
Comparer<TKey> keyComparer = Comparer<TKey>.Default;
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
TKey currentKey = selector(iterator.Current);
List<TElement> currentList = new List<TElement> { iterator.Current };
int sign = 0;
while (iterator.MoveNext())
{
TElement element = iterator.Current;
TKey key = selector(element);
int nextSign = Math.Sign(keyComparer.Compare(currentKey, key));
// Haven't decided a direction yet
if (sign == 0)
{
sign = nextSign;
currentList.Add(element);
}
// Same direction or no change
else if (sign == nextSign || nextSign == 0)
{
currentList.Add(element);
}
else // Change in direction: yield current list and start a new one
{
yield return currentList;
currentList = new List<TElement> { element };
sign = 0;
}
currentKey = key;
}
yield return currentList;
}
}
Completely untested, but I think it might work...
alternatively with linq operators and some abuse of .net closures by reference.
public static IEnumerable<IEnumerable<T>> Monotonic<T>(this IEnumerable<T> enumerable)
{
var comparator = Comparer<T>.Default;
int i = 0;
T last = default(T);
return enumerable.GroupBy((value) => { i = comparator.Compare(value, last) > 0 ? i : i+1; last = value; return i; }).Select((group) => group.Select((_) => _));
}
Taken from some random utility code for partitioning IEnumerable's into a makeshift table for logging. If I recall properly, the odd ending Select is to prevent ambiguity when the input is an enumeration of strings.
Here's a custom LINQ operator which splits a sequence according to just about any criteria. Its parameters are:
xs: the input element sequence.
func: a function which accepts the "current" input element and a state object, and returns as a tuple:
a bool stating whether the input sequence should be split before the "current" element; and
a state object which will be passed to the next invocation of func.
initialState: the state object that gets passed to func on its first invocation.
Here it is, along with a helper class (required because yield return apparently cannot be nested):
public static IEnumerable<IEnumerable<T>> Split<T, TState>(
this IEnumerable<T> xs,
Func<T, TState, Tuple<bool, TState>> func,
TState initialState)
{
using (var splitter = new Splitter<T, TState>(xs, func, initialState))
{
while (splitter.HasNext)
{
yield return splitter.GetNext();
}
}
}
internal sealed class Splitter<T, TState> : IDisposable
{
public Splitter(IEnumerable<T> xs,
Func<T, TState, Tuple<bool, TState>> func,
TState initialState)
{
this.xs = xs.GetEnumerator();
this.func = func;
this.state = initialState;
this.hasNext = this.xs.MoveNext();
}
private readonly IEnumerator<T> xs;
private readonly Func<T, TState, Tuple<bool, TState>> func;
private bool hasNext;
private TState state;
public bool HasNext { get { return hasNext; } }
public IEnumerable<T> GetNext()
{
while (hasNext)
{
Tuple<bool, TState> decision = func(xs.Current, state);
state = decision.Item2;
if (decision.Item1) yield break;
yield return xs.Current;
hasNext = xs.MoveNext();
}
}
public void Dispose() { xs.Dispose(); }
}
Note: Here are some of the design decisions that went into the Split method:
It should make only a single pass over the sequence.
State is made explicit so that it's possible to keep side effects out of func.
how can I create a dynamic ORDERBY in my LINQ CompiledQuery (e.g. supply Order Field and Direction as parameters for the compiled query)?
I would do it this way, first all you really need is a way to access the property value by string on an object. You could use reflection, but its slow. So use this helper class approach which is based on the tests of http://stefan.rusek.org/Posts/LINQ-Expressions-as-Fast-Reflection-Invoke/3/
public static class LINQHelper
{
public static IComparable OrderByProperty<TClass>(TClass item,
string propertyName)
{
var t = Expression.Parameter(typeof(TClass), "t");
var prop = Expression.Property(t, propertyName);
var exp = Expression.Lambda(prop, t).Compile();
return (IComparable)exp.DynamicInvoke(item);
}
}
The in your code where you want your order by string of property name, in this example col1, you just do the following.
var myQuery = from i in Items
select i;
myQuery.OrderBy(i=>LINQHelper.OrderByProperty(i,"col1"));
Hope this helps.
I think I found it:
Check out this link. It will point you to the VS2008 code samples which contains a Dynamic Linq Query Library which contains the extension method below. This will allow you to go:
Object.OrderBy("ColumnName");
Here is the extension methods, but you may want the whole library.
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) {
return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);
}
public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) {
if (source == null) throw new ArgumentNullException("source");
if (ordering == null) throw new ArgumentNullException("ordering");
ParameterExpression[] parameters = new ParameterExpression[] {
Expression.Parameter(source.ElementType, "") };
ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
Expression queryExpr = source.Expression;
string methodAsc = "OrderBy";
string methodDesc = "OrderByDescending";
foreach (DynamicOrdering o in orderings) {
queryExpr = Expression.Call(
typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
new Type[] { source.ElementType, o.Selector.Type },
queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
methodAsc = "ThenBy";
methodDesc = "ThenByDescending";
}
return source.Provider.CreateQuery(queryExpr);
}