简体   繁体   English

如何使用NUnit创建一个通用的BaseTest,我可以继承它并从基本运行中进行测试?

[英]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. 所以基本上我有一个域对象和一个可以用该对象进行CRUD操作的通用存储库。

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: 我想写一些集成测试(使用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);
    }
}

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). 这应该让我开始并给我一个失败的测试,因为throw将打破它(我也尝试实际实现方法没有运气)。 But the testrunners (tried both nunits GUI and resharpers test runner) just ignore my base test! 但是测试人员(尝试了nunits GUI和resharpers测试跑步者)只是忽略了我的基础测试! 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 所以我做了一点挖掘... NUnit在TextFixtureAttribute上有这个属性,让你指定你正在测试的是什么类型,所以我试着把属性

[TestFixture(typeof(Foo))]

On first the Base and also the Foo version. 首先是Base,还有Foo版本。 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). 当放在Foo版本时,它仍然只是忽略了从基础的测试,当我把它放在基础上...好吧它变成红色因为方法抛出异常,这将是好的,除非即使我做实际的实现在FooTests中,它们仍然无法工作(显然,基于TestFixture属性的Base测试永远不会知道哪些类继承它,所以如何知道找到实现)。

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... 我可以在基础测试类虚拟中进行测试,然后在FooBaseRepositoryTests中覆盖它,只是从base调用实现,这是一个蹩脚的解决方案,我认为......

What else is there to do? 还需要做什么? Am I missing something? 我错过了什么吗? Please help, someone... :) 请帮忙,有人...... :)

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: 我有一个通用的IRepository接口,我希望能够使用多个实现进行测试,因此我创建了一个在安装过程中忽略自身的基类,但是这个行为被其后代覆盖:

[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. 关于这一点的唯一稍微混乱的部分是基类创建了一堆“忽略”测试,这不是很干净。

When you're using the attribute [TestFixture(typeof(Foo))] on the fixture class in order to use it for different types; 当你在fixture类上使用属性[TestFixture(typeof(Foo))]时,为了将它用于不同的类型; it's not supposed to be abstract. 它不应该是抽象的。

If used on the Foo fixture, that class should be generic, and not typed for Foo. 如果在Foo fixture上使用,该类应该是通用的,而不是为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 http://www.nunit.org/index.php?p=testFixture&r=2.5.5

I have not tried out your example but you could try if you put the attributes TestFixture and Test in the same class. 我没有尝试过你的例子但你可以尝试将属性TestFixture和Test放在同一个类中。 Try also to put it into the base class. 还要尝试将其放入基类中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM