I understand how to pass one array to xUnit: Pass array of string to xunit test method
However, I'm in a situation where I want to pass three arrays to my test method:
Type1[] ReturnValuesForMock;
Type2[] ExpectedTestResult;
Type3[] TestData
Is there any way to do this? Type1 is an enum, so I can use a compile-time constant new [] {enum} but that doesn't work for Type2 which needs a call to new(). I can then deal with Type3 as params.
I feel like this really ought to be possible but I'm not sure how...
I'm not sure if this is the best way, but I've worked out that I can use the [ClassData] attribute on my tests like this:
[Theory]
[ClassData(typeof(TestDataGenerator))]
public void Test1(Type1[] t1, Type2[] t2, Type3[] t3)
{
//MyTest
}
And then provide the data through a TestDataGenerator class:
private class TestDataGenerator:IEnumerable<object[]>
{
private static readonly List<object[]> _data = new()
{
new object[]{new Type1[] {...}, new Type2[]{...)}, new Type3[]{...}},
...
};
public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Related
I have a test class and I want write a test for one of my functions and I have to use HashSet in [Theory] inlineData but I can't use it.
[Theory]
[InlineData(new HashSet<string>() {"text1","text2"}, "str")]
public void BuildInvertedIndexTest(ISet<string> expectedDocContain, string searchingWord)
I wrote classData and memberData but It wasn't successful.
please guide me.
With MemberDataAttribute the solution could look like this:
public static IEnumerable<object[]> BuildInvertedIndexTestData()
{
yield return new object[] { new HashSet<string>() { "text1", "text2" }, "str" };
yield return new object[] { ... };
}
The usage would look like this:
[Theory, MemberData(nameof(BuildInvertedIndexTestData))]
public void BuildInvertedIndexTest(ISet<string> expectedDocContain, string searchingWord)
I haven't tested this solution so it might happen that you need to change the expectedDocContain parameter's type to HashSet<string>.
You cannot use HashSet<T> with [InlineData] as attributes only support simple types like string, int, bool, arrays etc.
You will need to use another way of parameterising the test, such as [MemberData] for ISet<T>/HashSet<T> which you can read more about in this blog post by Andrew Lock: https://andrewlock.net/creating-parameterised-tests-in-xunit-with-inlinedata-classdata-and-memberdata/
Alternatively, you could use a string[] with [InlineData] and construct the HashSet<string> from that in the body of the test.
[Theory]
[InlineData(new string[] {"text1","text2"}, "six")]
public void BuildInvertedIndexTest(string[] expectedDocContain, string searchingWord)
{
var hashSet = new HashSet<string>(expectedDocContain);
// TODO Put the rest of your test here.
}
I have a generic class A<T>, that implements IEnumerable<T[]>.
I want to have a convenience wrapper B that inherits from A<char> and implements IEnumerable<string>.
public class A<T> : IEnumerable<T[]>
{
public IEnumerator<T[]> GetEnumerator()
{
return Enumerate().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
protected IEnumerable<T[]> Enumerate()
{
throw new System.NotImplementedException();
}
}
public class B : A<char>, IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
return Enumerate().Select(s => new string(s)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Now, this works perfectly fine, foreach variable type is inferred to be string:
B b = new B();
foreach (var s in b)
{
string[] split = s.Split(' ');
}
But this won't compile, saying "The type arguments cannot be inferred from usage, try specifying the type arguments explicitly":
string[] strings = b.ToArray();
However, this works:
string[] strings = b.ToArray<string>();
Can anyone explain this compiler behavior?
Obviously, B implements both IEnumerable<char[]> and IEnumerable<string> and probably it can't figure out which of them I want to call, but why it works fine in "foreach" sample?
Please, don't suggest me to solve my problem by composition - this is the last resort for me.
The difference is the following:
foreach actually looks for a public method called GetEnumerator. It doesn't really care for IEnumerable<T>. Your class B only has one public method named GetEnumerator: The one defined in B which hides the one defined in A.
ToArray on the other hand is an extension method on IEnumerable<T>. As your class is both IEnumerable<string> and IEnumerable<char[]> the call is ambiguous between the two generic arguments string and char[].
foreach loop does not use IEnumerable or IEnumerable<T> implementation. You can use foreach even if your class doesn't implement any of them. The only thing it needs is GetEnumerator method that returns IEnumerator implementation.
Check this question: How is foreach implemented in C#?
That's why your class works with foreach and doesn't with ToArray().
I have a class using the List class. When attempting to set up the Add function to add my anonymous type, all I get is errors.
I've been searching for hours and as best I can tell, every example I've seen is doing the same thing. So I don't understand what's wrong.
class fileHistory<Object> : List<Object>
{
public new void Add(DateTime ts, int st)
{
base.Add( new { timeStamp = ts; status = st;} );
}
}
You don't need a generic declaration in your class definition, and you also need to change semicolons to commas:
public class fileHistory : List<Object>
{
public new void Add(DateTime ts, int st)
{
base.Add( new { timeStamp = ts, status = st} );
}
}
Right, you can overwrite (not polymorphism! check I used the word overwrite instead of override) List<T>.Add(T) method, but I believe that you could solve your issue using composition instead of inheritance and your code will work flawlessly:
class fileHistory
{
private readonly List<object> _log = new List<object>();
public void Add(DateTime ts, int st)
{
_log.Add( new { timeStamp = ts; status = st;} );
}
}
BTW, I see three design flaws here:
Anonymous types aren't meant to your use case. If you are adding objects with these two properties and you do it in a concrete use case like yours, maybe you're using anonymous types because of your laziness of designing a class with 2 properties??? ;)
Because of #1, why you would create a list of objects using a generic list? It defeats the entire purpose of generics!!
I find a bad design decision hidding Add of List<T>. Use composition instead of inheritance in these cases. Also, I don't know why you're using identifier re-using with new keyword when C# supports method overloading. In List<T> there's no overload of Add with your input parameters...
My advise is: code isn't fancier because of using fancy syntactic sugar provided by C#. Sometimes you don't need it, and honestly, I believe this is the case.
For those who're worried about LINQ...
Any class might or might not implement IEnumerable<T>. The whole fileHistory class can be iterated with foreach or LINQ and its extension methods implementing IEnumerable<T>:
// Check that I dropped the lazy approach of using
// anonymous types!!
class fileHistory : IEnumerable<FileLog>
{
private readonly List<FileLog> _log = new List<FileLog>();
public IEnumerator<FileLog> GetEnumerator()
{
return _log.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _log.GetEnumerator();
}
public void Add(DateTime ts, int st)
{
_log.Add(new FileLog { timeStamp = ts; status = st;} );
}
}
...and now some class like this can be iterated even when using composition instead of inheritance:
new fileHistory().Where(log => log.DateTime < DateTime.Now);
class fileHistory<Object> : List<Object>
{
public new void Add(DateTime ts, int st)
{
// That's how it's supposed to be
base.Add(new { timeStamp = ts, status = st });
}
}
Hope I've helped!
In JQuery you can write $('.my-class').hide() and it will call hide() on all the results. There's no for loop, no iterating, no LINQ extensions and lambdas etc. and it makes dealing with lists super fun. I want to be able to have this functionality on IEnumerables in C#. I think Matlab has a similarly concise syntax when operating on arrays/matrices.
Long story short, I want the following code (or similar) to work:
class Program
{
static List<MyClass> MyList = new List<MyClass>();
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
MyList.Add(new MyClass());
MyList.MyMethod();
// should be exactly equivalent to:
MyList.Select(n => n.MyMethod());
}
}
class MyClass
{
public int MyMethod() { return 123; }
}
I'm aware this is possible on a case-by-case basis using extension methods:
public static IEnumerable<int> MyMethod(this IEnumerable<MyClass> lst)
{
return lst.Select(n => n.MyMethod());
}
But we'd have to create one extension method for every single method on every single type that you wanted this behaviour on.
Ideally this would be possible for all types and all methods and still be type-safe at compile time. I suspect I'm asking too much from the C# language here, but how would we do this or something similar in a as-generic-as-possible way?
Possible solutions:
Auto-generate extension methods for particular types. If we only intend to use this notation for a few types, we could just generate the extension methods once automatically. This would achieve the exact syntax and full type safety but generating code would be a pain.
A single extension method that returns a dynamic object built using reflection on the supplied type. The idea is that we'd use reflection to iterate through the type's methods and build up a dynamic object that would have all the methods like .MyMethod() that would behind the scenes call Select(...) on the IEnumerable. The syntax would end up being something like MyList.Selector().MyMethod(). But now we've lost the syntax and type safety. Clever, maybe. Useful, probably not.
Intercepting method calls? Is it possible to decide how to react to a method call at runtime? I don't know. Again you'd lose type safety.
The most simple solution is using dynamic objects. If you are willing to throw away type safety, you can make a IEnumerable type that behaves statically when needed and dynamically otherwise, here's a sample prototype:
public class DynamicIEnumerable<T> : DynamicObject, IEnumerable<T>
{
public IEnumerable<T> _enumerable;
public DynamicIEnumerable(IEnumerable<T> enumerable)
{
this._enumerable = enumerable;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
result = new DynamicIEnumerable<T>(_enumerable.Select(x => (T)typeof(T).InvokeMember(binder.Name, BindingFlags.InvokeMethod, null, x, null)));
return true;
}
public IEnumerator<T> GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
}
In TryInvokeMember, the invoked member on IENumerable is applied on all items using reflection. The only constraints on this approach is that you have to return this in invoked method. Here's a sample of how to use this approach:
public class SomeClass
{
public int Value {get;set;}
public SomeClass(int value)
{
this.Value = x;
}
public SomeClass Plus10()
{
Value += 10;
return this;
}
}
static void Main()
{
dynamic d = new DynamicIEnumerable<X>(Enumerable.Range(0, 10).Select(x => new SomeClass(x)));
foreach (var res in d.Plus10().Plus10())
Console.WriteLine(res.Value);
}
how would we do this or something similar in a as-generic-as-possible way?
This isn't a pretty solution but it does work:
public class MyClass
{
public void MyMethod()
{
}
public void MyMethod2()
{
}
}
Extension Method:
public static class WeirdExtensions
{
public static IEnumerable<T> CallOnAll<T>(this IEnumerable<T> instance ,
Action<T> call)
{
foreach(var item in instance)
{
call(item);
}
return instance;
}
}
Usage (chaining/fluent):
var blah = new List<MyClass>();
blah.CallOnAll(b => b.MyMethod())
.CallOnAll(b => b.MyMethod2());
Notes
This isn't quite possible due to a the underlying assumption that you'd have to every single method on every single type. In jQuery/Html there is only one underlying type of an Html Element. All elements are exposed to the same methods (whether or not the type supports it). In jQuery, you can call $('head').hide() but it won't do anything visually, but because it is an element, it will be inline styled. If you need a new method, you do have a build one, but for only one type because there is only one type.
In contrast with C# you build your types (many many types) and they all have different methods (sure there could be overlap).
This is a simple contrived example, but hopefully will illustrate my query.
public class Test
{
public string Name = "test";
}
public static class Ext
{
public static Test ConvertToTest<T1>(this T1 source)
{
return new Test();
}
public static T2 Convert<T1,T2>(this T1 source) where T2 : new()
{
return new T2();
}
}
ConvertToTest only needs one Type, so the following compile
Ext.ConvertToTest<string>("hello");
"hello".ConvertToTest();
The last uses type-interfence and this means it also works with anonymous classes, eg
var anon = (new { Name = "test" }) ;
anon.ConvertToTest();
However this is hardcoded to always use the class Test, whereas I want to be able to specify the type as in the second method
I can write
Ext.Convert<string, Test>("hello");
and this compiles, because I know both types at compile time, but I can't use it with anonymous classes, and I can't find a way of using type-inference plus the extra Type
It would be nice if I could do something like
anon.Convert<,Test>() ;
and the compiler would know to use inference for the first type (which isn't specified) and use Test as the second type.
Is there any way around this issue?
You can't do what you're asking on a single method, but if you're clever and willing to define a couple of different classes you should be able to make syntax like this possible:
var test = Ext.Convert("hello").To<Test>();
Just make Convert be based on a single generic type, and have it return a generic type based on that:
public Converter<T> Convert<T>(T source)
{
return new Converter<T>(source);
}
Then add a method to the type it returns which serves as a basic wrapper for your original method:
public class Converter<T>
{
T _source;
internal Converter(T source)
{
_source = source;
}
public T2 To<T2>()
{
return Ext.Convert<T, T2>(_source);
}
}
There is a way to do what you want. You use a template pattern - it's a little bit of a kludge but it allows you to infer both types. It can also be use to infer anonymous types.
Here it is:
public static T2 Convert<T1,T2>(this T1 source, Func<T2> template)
where T2 : new()
{
return new T2();
}
You can call it like this:
var anon = (new { Name = "test" }) ;
anon.Convert(() => new Test());
Which isn't too far from your pseudo-code.