I want to test a unit test with generics, and I am STRUGGLING to find the right way.
I have this
[TestCase(typeof(CalendarGeneralCsv), typeof(CalendarGeneralCsvMap), 121)]
public void ReadFromCsvFileWithConfigurationMapTest<T,Tmap>(T t, Tmap tmap, int totalRowsExptected)
{
//Arrange
//Act
var records = csvService.ReadFileCsv<T, Tmap>(_csvToRead, ",") as IEnumerable<object>;
var result = new List<object>(records);
//Assert
result.Should().NotBeNullOrEmpty();
result.Should().HaveCount(totalRowsExptected);
}
The error is in this line
var records = csvService.ReadFileCsv<T, Tmap>(_csvToRead, ",") as IEnumerable<object>;
Saying that T, and Tmap must be a reference type.
I would not usually reply where there is already several answers and one is accepted, but they all seem to be based on the assumption that test methods can't be generic. They definitely can. My memory tells me this was once well-documented, but it doesn't seem to be any longer - or my memory is wrong - which explains why you might not think it's possible.
It's possible a generic solution may not be best here, but it seems like a fun thing to try and may either be better or clarify why the accepted solution is better. I can only go so far with the info already provided, but if jolynice will collaborate, maybe we can learn something. :-)
So... here is an initial shot at a solution, which I'll edit if more info comes back.
The original solution in the question causes an error because the constraints in the generic method ReadFileCsv<T, Tmap>(...) are not met. We don't know what they are, but from the error they include T : class and Tmap : class. So the first step to a correct answer is to reproduce all the constraints of the method being called on the test method itself.
UPDATE: This code doesn't actually work. Short story, I have the feature locally and I thought it had been added to NUnit but it has not. See UPDATE text below as well...
[TestCase(typeof(CalendarGeneralCsv), typeof(CalendarGeneralCsvMap), 121)]
public void ReadFromCsvFileWithConfigurationMapTest<T,Tmap>(int totalRowsExptected)
where T : class
where Tmap : class
{
//Arrange
//Act
var records = csvService.ReadFileCsv<T, Tmap>(_csvToRead, ",") as IEnumerable<object>;
var result = new List<object>(records);
//Assert
result.Should().NotBeNullOrEmpty();
result.Should().HaveCount(totalRowsExptected);
}
UPDATE in response to @Jannes comment
You can create a generic method without parameters in C#. If you used such a method as a test method, NUnit would need to know the actual types to use to call it. Unfortunately, there is no such way.
Currently, NUnit can only deduce the actual types from arguments you provide. That means there has to be at least one argument for each parameter Type of the generic method.
This is clearly a gap in NUnit and it has been discussed in various issues on GitHub. So far, no proposal has been accepted. See issues 150, 1215, 2562 and 3576 at https://github.com/nunit/nunit/issues for example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With