Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a generic BaseTest with NUnit that I can inherit from and have tests from the base run?

So basically i have a domain object and a generic repository that can do CRUD operations with that object.

public interface IBaseRepository<T> where T : BaseEntity
{
    void Add(T entity);
    void Remove(T entity);
    T ById(int id);
    IEnumerable<T> All();
}

So I have several implementations of this interface, one for each domain object.

I would like to write some integration tests (using nunit) and for that i figured i'd make a BaseRepositoryTest - like this:

public abstract class BaseRepositoryTests<T> where T : BaseEntity
{
    public abstract IBaseRepository<T> GetRepository();
    public abstract T GetTestEntity();

    [Test]
    public void AddWhenCallingAddsObjectToDatabase()
    {
        IBaseRepository<T> repository = GetRepository();
        T entity = GetTestEntity();

        repository.Add(entity);
    }
}

Now, for each domain object i would have to implement how to initialize the Repository and how to create a test entity, which seems fair, given they would be different...

All i have to do now is writing the actual test fixture right? Like this:

[TestFixture]
public class FooRepositoryTests: BaseRepositoryTests<Foo>
{
    public override IBaseRepository<Foo> GetRepository()
    {
        throw new NotImplementedException();
    }

    public override Foo GetTestEntity()
    {
        throw new NotImplementedException();
    }
}

This should get me started and give me a failed test since the throw will break it (i also tried actually implementing the methods with no luck). But the testrunners (tried both nunits GUI and resharpers test runner) just ignore my base test! It shows up and all - but reported back as Ignored.

So i did a little bit of digging... NUnit have this property on the TextFixtureAttribute that lets you specify what kind of you are testing so i tried putting the attribute

[TestFixture(typeof(Foo))]

On first the Base and also the Foo version. When put on the Foo version it still just ignores the test from the base, and when i put it on the base... well it turns red because the methods throws exceptions, which would be good except that even when i do the actual implementation in FooTests, they still won't work (obviously the Base test given the TestFixture attribute would never know what classes inherit from it, so how would it know to find the implementation).

So what am I stuck to do? I could make the test in the base test class virtual and then override it in FooBaseRepositoryTests, only to call the implementation from base, which is a lame solution i think...

What else is there to do? Am I missing something? Please help, someone... :)

like image 336
Per Hornshøj-Schierbeck Avatar asked Aug 31 '10 19:08

Per Hornshøj-Schierbeck


People also ask

How do I create a unit test project using NUnit?

.NET Core 2.1 SDK or later versions. A text editor or code editor of your choice. Open a shell window. Create a directory called unit-testing-using-nunit to hold the solution. Inside this new directory, run the following command to create a new solution file for the class library and the test project:

What is testfixture in NUnit?

The [TestFixture] attribute denotes a class that contains unit tests. The [Test] attribute indicates a method is a test method. Save this file and execute dotnet test to build the tests and the class library and then run the tests. The NUnit test runner contains the program entry point to run your tests.

What is the use of NUnit report generator?

The NUnit report generated using the Extent Framework provides insightful information about the tests, environment values, devices against which tests were conducted, and more. It also lets you create Gherkin-style tests, due to which Extent Reports can be used as an NUnit report generator for BDD tests.

What does the [test] attribute indicate in a NUnit Test?

The [Test] attribute indicates a method is a test method. Save this file and execute dotnet test to build the tests and the class library and then run the tests. The NUnit test runner contains the program entry point to run your tests. dotnet test starts the test runner using the unit test project you've created.


2 Answers

I had this issue recently and found a different workaround. I have a generic IRepository interface that I want to be able to test with multiple implementations, so I created a base class that ignores itself during setup, but this behavior is overridden by its descendants:

[TestFixture]
public class AbstractRepositoryTests
{
    protected IRepository _repository;

    [SetUp]
    public virtual void SetUp()
    {
        Assert.Ignore();
    }

    [Test]
    public void AddToRepository()
    {
        // Place logic using _repository here
    }
}

I then override the setup behavior in my descendant to instantiate a repository object rather than ignoring all tests:

public class InMemoryRepositoryTests : AbstractRepositoryTests
{
    [SetUp]
    public override void SetUp()
    {
        _repository = new InMemoryRepository<string>();
    }
}

The derived class will run all of its parent tests properly. The only slightly messy part about this is that the base class creates a bunch of "Ignored" tests, which isn't very clean.

like image 132
Evan M Avatar answered Sep 21 '22 14:09

Evan M


When you're using the attribute [TestFixture(typeof(Foo))] on the fixture class in order to use it for different types; it's not supposed to be abstract.

If used on the Foo fixture, that class should be generic, and not typed for Foo.

From the docs:

[TestFixture]
public class AbstractFixtureBase
{
    ...
}

[TestFixture(typeof(string))]
public class DerivedFixture<T> : AbstractFixtureBase
{
    ...
}

http://www.nunit.org/index.php?p=testFixture&r=2.5.5

like image 21
Martin R-L Avatar answered Sep 21 '22 14:09

Martin R-L