How to use multiple TestCaseSource attributes for an N-Unit Test - c#

How do you use multiple TestCaseSource attributes to supply test data to a test in N-Unit 2.62?
I'm currently doing the following:
[Test, Combinatorial, TestCaseSource(typeof(FooFactory), "GetFoo"), TestCaseSource(typeof(BarFactory), "GetBar")]
FooBar(Foo x, Bar y)
{
//Some test runs here.
}
And my test case data sources look like this:
internal sealed class FooFactory
{
public IEnumerable<Foo> GetFoo()
{
//Gets some foos.
}
}
internal sealed class BarFactory
{
public IEnumerable<Bar> GetBar()
{
//Gets some bars.
}
}
Unfortunately, N-Unit won't even kick off the test since it says I'm supplying the wrong number of arguments. I know you can specify a TestCaseObject as the return type and pass in an object array, but I thought that this approach was possible.
Can you help me resolve this?

The appropriate attribute to use in this situation is ValueSource. Essentially, you are specifying a data-source for every argument, like so.
public void TestQuoteSubmission(
[ValueSource(typeof(FooFactory), "GetFoo")] Foo x,
[ValueSource(typeof(BarFactory), "GetBar")] Bar y)
{
// Your test here.
}
This will enable the type of functionality I was looking for using the TestCaseSource attribute.

Related

C# pattern matching with base class and generic type

I have this piece of code that checks if an object is of type Sequence<T> which works as intended for objects of Type Task.
public class Sequence<T> {}
public class Task : Sequence<Task> {}
public class Program
{
public static void Main()
{
var task = new Task();
// These two are equivalent
Console.WriteLine(IsSequence(task));
Console.WriteLine(task is Sequence<Task>);
}
public static bool IsSequence<TEntity>(TEntity entity)
{
return entity is Sequence<TEntity>;
}
}
Now, however, I have a new requirement where these other types Tool and Assembly should also match, and I am pretty new to the pattern matching in C#, so not sure how to achieve it.
public class Sequence<T> {}
public abstract class Item : Sequence<Item> {}
public class Task : Sequence<Task> {}
public class Tool : Item {}
public class Assembly : Item {}
public class Program
{
public static void Main()
{
var ta = new Tool();
var tt = new Assembly();
var task = new Task();
Console.WriteLine(IsSequence(ta));
Console.WriteLine(IsSequence(tt));
Console.WriteLine(IsSequence(task));
// What I am posting here is an oversimplification of the real scenario
// This code for checking if something is a Sequence or not is
// handled by a core class with shared functionality that can't know or use the
// proper typed overload required.
//
// So doing this is not an option:
//
// Console.WriteLine(IsSequence<Item>(ta));
// This is how the output should be
Console.WriteLine(ta is Sequence<Item>);
Console.WriteLine(tt is Sequence<Item>);
Console.WriteLine(task is Sequence<Task>);
}
public static bool IsSequence<TEntity>(TEntity entity)
{
// How to rewrite (if possible) this pattern matching so that Task, Tool and Assembly match?
// So basically I want to know if either TEntity or some of the base types is Sequence<base>
return entity is Sequence<TEntity>;
}
}
I know that the way it is currently written, it won't match since Tool/Assembly are not Sequence<Tool>/Sequence<Assembly>, so I need a way to rewrite the pattern matching to check if it's Sequence<Item>.
Here is a C# Online Fiddle with this example.
The way you wrote your function won't work because Tool is not a Sequence<Tool>, it's a Sequence<Item>.
There are many, many ways to write your function if you choose to keep it, for whatever reason, but I'll give you two ways.
First, you can write it to receive an object argument then use is Sequence<T> inside to figure out if it's a sequence of something. The problem with this is that you need to provide the type argument every time, there's no inference here.
Second, you can write it like this:
public static bool IsSequence<TEntity>(Sequence<TEntity> entity) => true;
public static bool IsSequence(object obj) => false;
In this case there's no need to provide the type argument, just call it with your object and it will return the correct value. And since it relies on compile-time overload resolution, it's very efficient at runtime. Plus it should look familiar to any C++ programmer!
As a third option, extract an interface ISequence from your Sequence<T> class and then simply test with is ISequence with no type argument, since you don't seem to care about it in the test.

NUnit extending ICommandWrapper How do I wrap a TestCase?

I tried extending extending ICommandWrapper, following this article: https://www.skyrise.tech/blog/tech/extending-nunit-3-with-command-wrappers/. I figured out that I can also extend TestAttribute and it just works, then I tried extending TestCaseAttribute:
[AttributeUsage(AttributeTargets.Method), AllowMultiple = true]
public class MyTestCaseAttribute : TestCaseAttribute, IWrapSetUpTearDown
{
private object[] _args;
public MyTestCaseAttribute(params object[] args) : base(args)
{
_args = args;
}
public TestCommand Wrap(TestCommand command)
{
return new MyTestCommand(command, _args);
}
}
MyTestCommand extends DelegatingTestCommand, just like in the article.
The problem is, if I add multiple MyTestCaseAttributes to a test method, the test method gets wrapped by MyTestCommand.Execute's code multiple times.
[EDIT] Example:
Suppose MyTestCommand looks like this:
public abstract class MyCommandDecorator : DelegatingTestCommand
{
public override TestResult Execute(TestExecutionContext context)
private object[] _testCaseArgs;
protected TestCommandDecorator(TestCommand innerCommand, params object[] args) : base(innerCommand)
{
_testCaseArgs = args;
}
public override TestResult Execute(TestExecutionContext context)
{
DoSomething(_testCaseArgs);
return context.CurrentResult = innerCommand.Execute(context);
}
}
Suppose I decorate a test method with two [MyTestCase] attributes:
[MyTestCase(1)]
[MyTestCase(2)]
public void MyTest(int foo)
{
//...
}
The desired behaviour is something like:
DoSomething(1);
MyTest(1);
DoSomething(2);
MyTest(2);
But actual behaviour is:
DoSomething(2)
DoSomething(1)
MyTest(1)
DoSomething(2)
DoSomething(1)
MyTest(1)
The key to your problem is this... C# allows you to decorate a method or a class with an attribute. But an individual test case doesn't exist outside of NUnit - there is no C# equivalent - so you can't decorate it.
IOW your two Attributes apply to the method and cause NUnit to use that method to generate two test cases. However, your attributes also implement ICommandWrapper, which causes NUnit to wrap any test cases it generates. One part of NUnit is looking for test cases to create another part is looking for attributes to wrap test cases. Those two parts are entirely separated.
That's why NUnit uses properties on the test case method to indicate things like Ignoring the case. It can't use an attribute because an attribute would apply to every test case generated by that method.
Hopefully, that explains what's happening.
To get past the problem, your command wrapper should only apply itself to a test that was generated by that particular instance of the attribute. That means you have to get involved in the creation of the test, at least to the extent that your attribute remembers the reference to the test it created. This is a bit complicated, but you should look at the code for TestCaseAttribute to see how the test case is created.
Figured it out.
Instead of extending TestCaseAttribute, I can extend TestAttribute and obtain the arguments to pass to the wrapper class from standard TestCaseAttributes using command.Test.Arguments.
[AttributeUsage(AttributeTargets.Method), AllowMultiple = true]
public class MyTestAttribute : TestAttribute, IWrapSetUpTearDown
{
public TestCommand Wrap(TestCommand command)
{
return new MyTestCommand(command, command.Test.Arguments);
}
}
[TestCase(1)]
[TestCase(2)]
[MyTest]
public void MyTest(int foo)
{
//...
}

How to combine AutoDataAttribute with InlineData

I heavily use the Autofixture AutoData Theories for creating my data and mocks. However this prevents me from using the InlineData Attributes from XUnit to pipe in a bunch of different data for my tests.
So I am basically looking for something like this:
[Theory, AutoMoqDataAttribute]
[InlineData(3,4)]
[InlineData(33,44)]
[InlineData(13,14)]
public void SomeUnitTest([Frozen]Mock<ISomeInterface> theInterface, MySut sut, int DataFrom, int OtherData)
{
// actual test omitted
}
Is something like this possible?
You'll have to create your own InlineAutoMoqDataAttribute, similar to this:
public class InlineAutoMoqDataAttribute : InlineAutoDataAttribute
{
public InlineAutoMoqDataAttribute(params object[] objects) : base(new AutoMoqDataAttribute(), objects) { }
}
and you'd use it like this:
[Theory]
[InlineAutoMoqData(3,4)]
[InlineAutoMoqData(33,44)]
[InlineAutoMoqData(13,14)]
public void SomeUnitTest(int DataFrom, int OtherData, [Frozen]Mock<ISomeInterface> theInterface, MySut sut)
{
// actual test omitted
}
Note that the inlined data, the ints in this case, must be the first parameters of the test method.
All the other parameters will be provided by AutoFixture.
With the latest AutoFixture, you can use Inline AutoData Theories
Uses the InlineData values for the the first method arguments, and then uses AutoData for the rest (when the InlineData values run out).

Polymorphism and explicit Casting

I have the following architecture(the analogy sucks but W/E).
In program and other logic classes I have lots of methods that uses the specific type of the finger (MonkeyFinger). This mean that i have to explicitly cast in all those testMethods.
Is there any design pattern/solution to avoid explicit casts?
EDIT Code:
Monkey govi = new Monkey(...)
Program test = new Program()
test.testFinger1((MonkeyFinger) govi.GetHand.getFinger)
...
You can try something like this:
public class Animal<TFingerType> where TFingerType : IFinger
{
Hand<TFingerType> GetHand()
{
//... Do something
}
}
public class Monkey : Animal<MonkeyFinger> { }
public class Hand<TFingerType> where TFingerType : IFinger
{
}
public interface IFinger
{
}
public class MonkeyFinger : IFinger {
}
At least in your given example, it doesn't make sense for a Monkey to return a hand which contains HumanFingers. The hand itself is really defined by what type of fingers it has.
Then your code becomes:
Monkey govi = new Monkey(...)
Program test = new Program()
test.testFinger1(govi.GetHand.getFinger() /* getFinger here returns a MonkeyFinger */)
Note that the fingers are still IFingers, and can be used in that context, but this approach also provides concretely typed fingers.
I think it is best to create a method to do the checking for you. And yes, the casting is necessary if you want to test on some assumptions (like a monkey having only monkey fingers).
Something like:
public static T TestAndConvert<T>(object o)
{
Assert.IsInstanceOfType(o, typeof(T));
return (T)o;
}
Here you first check if the type is correct and then you return a typed instance. This way you are sure the type is correct and you have proper testing.
Use it in your test calls:
testFinger1(TestAndConvert<MonkeyFinger>(finger));
(From your diagram I am not sure if you use an automated test framework, like Unit Tests in Visual Studio, I recommend to do so)
Is there a real need to pass concrete finger to test method? When you are using interface you are define a contract which each implementation should follow. You can extend parent behavior in child class (or replace it but it's not correspondent with Liskov substitution principle) with method overriding but you test only contract then why do you need to pass MonkeyFinger insted of IFinger in test method?

C# generic return with generic type set in the method not in the call

I am trying to setup a method that retrieves data from a database, and based on data in there it will create and hydrate a class with a generic component.
public class MyObject<T> where T : BaseMyType
{
T MyTypedObject { get; set; }
}
public class MyType1 : BaseMyType
{
string Key { get; set; }
}
public class MyType2 : BaseMyType
{
Guid Id { get; set; }
}
public MyObject<T> MyMethod<T>() where T : BaseMyType
{
if(Situation1)
return new MyObject(MyType1);
else
return new MyObject(MyType2);
}
This code complains that MyObject<MyType1> cannot be converted to MyObject<T>. Now I need to use it like this:
var myObject = MyMethod();
The call of course complains it cannot infer the type from the usage. I understand the compiler error messages, I just am not sure how to do what I need.
It can't be done, but…let's suppose for a moment that we could figure out a way for the following statement to compile in the way that you want:
var myObject = MyMethod();
Then what is the code using myObject going to look like? In this hypothetical scenario, the variable myObject will sometimes have the type MyType1 and sometime have the type MyType2. Will the code using myObject care about that?
If all that code will do is use members of the shared base type (i.e. BaseMyType), then the fix is easy. Just forget about the generic approach:
public BaseMyType MyMethod()
{
if(Situation1)
return new MyType1();
else
return new MyType2();
}
If it does care about the differences (i.e. needs to access either Key or Id depending on the type that was returned), then even if you could do the impossible, the calling code is still going to need to conditionally handle the individual scenarios based on the Situation1 variable. Which would mean that you put the check for Situation1 in the wrong place.
Instead, your caller should look more like this:
if (Situation1)
{
MyType1 myObject = MyMethod1();
// do situation 1 stuff
}
else
{
MyType2 myObject = MyMethod2();
// do situation 2 stuff
}
Where the implementation of your original MyMethod() has been split into two methods, MyMethod1() and MyMethod2(), corresponding to the two scenarios. Again, note the complete lack of generics as part of the implementation. It's not called for, and won't work.
It's even possible that you need a polymorphic implementation of the caller, i.e. so you don't have to check Situation1 more than once. But without a good, minimal, complete code example it would be impossible to comment more thoroughly on that possibility.

Categories