I have an api with a 'listing' method that supports some filtering capability. I wanted to write an integration test in xUnit that setup the data once in the database, then run several different iterations of filtering against the data.
Below is not correct as it runs the test method for each InlineData and populates the database.
[Theory]
[InlineData( "File_1_CE.xlsm", 1 )]
[InlineData( "File_1_CE", 2 )]
public async Task GetListing_WithNameFilters_ReturnsCorrectResults( string name, int expected )
{
// Arrange
// Want to create some data that is shared across all InlineData (or TheoryData<T>) runs...
await factory.FooBarCreateListingTestData();
using var client = factory.CreateClient();
// Act
var response = await client.GetAsync( Contracts.V1.ApiEndpoints.CalcEngines.Build.Listing( new [] { name } ) );
var result = ( await response.Content.ReadFromJsonAsync<Contracts.V1.Responses.ListResult<Contracts.V1.Responses.ManagedFileInfo>>() )!;
// Assert - Response has single result
response.StatusCode.Should().Be( HttpStatusCode.OK );
result.Should().NotBeNull();
result.Total.Should().Be( check.Expected );
result.Items.Should().HaveCount( expected );
}
If I wanted to use a [Theory] pattern, I believe my only options are:
- In the test, use a
try/finallyto create the data each time and in thefinallydestroy the data. - Create a separate class for just my 'listing test' and use the
IClassFixture<T>pattern and populate the database in theInitializeAsyncmethod and destroy it in theDisposeAsyncmethod.
I don't like option 1 because I was trying to eliminate the overhead of creating and destroying data in the database for every theory run. I don't like option 2 because I wanted to group all my 'Get' method tests in a single class (as is common practice my many - especially those on my team) and I didn't want to make a separate class just for the GetListing method.
But maybe these are my only options?