Как я могу создать базовый базовый тест с NUnit, от которого я могу наследовать и получить тесты из базового прогона? - PullRequest
12 голосов
/ 31 августа 2010

Итак, в основном у меня есть объект домена и общий репозиторий, который может выполнять операции CRUD с этим объектом.

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

Итак, у меня есть несколько реализаций этого интерфейса, по одной для каждого объекта домена.

Я хотел бы написать несколько интеграционных тестов (используя nunit), и для этого я решил сделать BaseRepositoryTest - вот так:

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);
    }
}

Теперь для каждого объекта домена мне нужно было бы реализовать, как инициализировать репозиторий и как создать тестовую сущность, что выглядит справедливо, учитывая, что они будут разными ...

Все, что мне нужно сейчас сделать, это написать настоящий тестовый прибор, верно? Как это:

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

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

Это должно привести меня к началу и дать мне неудачный тест, так как бросок сломает его (я также попытался на самом деле реализовать методы без удачи). Но тестеры (пробовавшие как графический интерфейс для nunits, так и reharpers) просто игнорируют мой базовый тест! Он обнаруживается и все - но сообщается как игнорируется.

Итак, я немного покопался ... У NUnit есть это свойство в TextFixtureAttribute, которое позволяет вам указать, какого типа вы тестируете, поэтому я попытался поместить атрибут

[TestFixture(typeof(Foo))]

На первой версии Base, а также на версии Foo. При установке на версию Foo он все равно просто игнорирует тест из базы, а когда я ставлю его на базу ... ну, он становится красным, потому что методы выдают исключения, что было бы хорошо, за исключением того, что даже когда я делаю фактическую реализацию в FooTests они по-прежнему не будут работать (очевидно, что базовый тест с учетом атрибута TestFixture никогда не будет знать, какие классы наследуют от него, поэтому откуда он узнает, чтобы найти реализацию).

Так что же мне делать? Я мог бы сделать тест в базовом тестовом классе виртуальным, а затем переопределить его в FooBaseRepositoryTests, только чтобы вызвать реализацию из базы, которая, как мне кажется, является неудачным решением ...

Что еще можно сделать? Я что-то пропустил? Пожалуйста, помогите, кто-нибудь ...:)

Ответы [ 3 ]

2 голосов
/ 04 февраля 2011

У меня недавно была эта проблема, и я нашел другой обходной путь. У меня есть общий интерфейс IRepository, который я хочу иметь возможность тестировать с несколькими реализациями, поэтому я создал базовый класс, который игнорирует себя во время установки, но это поведение переопределяется его потомками:

[TestFixture]
public class AbstractRepositoryTests
{
    protected IRepository _repository;

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

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

Затем я переопределяю поведение установки в моем потомке, чтобы создать экземпляр объекта репозитория, а не игнорировать все тесты:

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

Производный класс будет правильно запускать все родительские тесты. Единственная немного запутанная часть этого - то, что базовый класс создает кучу «игнорируемых» тестов, которые не очень чисты.

1 голос
/ 02 сентября 2010

Когда вы используете атрибут [TestFixture(typeof(Foo))] в классе приборов, чтобы использовать его для разных типов;это не должно быть абстрактным.

Если используется в приборе Foo, этот класс должен быть универсальным, а не типизированным для Foo.

Из документов:

[TestFixture]
public class AbstractFixtureBase
{
    ...
}

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

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

0 голосов
/ 31 августа 2010

Я не пробовал ваш пример, но вы можете попробовать, если вы поместите атрибуты TestFixture и Test в один класс.Попробуйте также поместить его в базовый класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...