2010-08-31 27 views
11

Vì vậy, về cơ bản tôi có một đối tượng miền và một kho lưu trữ chung có thể thực hiện các hoạt động CRUD với đối tượng đó.Làm thế nào tôi có thể tạo một BaseTest chung với NUnit mà tôi có thể kế thừa và có các thử nghiệm từ chạy cơ sở?

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

Vì vậy, tôi có một số triển khai của giao diện này, một cho mỗi đối tượng miền.

Tôi muốn viết một số bài kiểm tra tích hợp (sử dụng nunit) và cho rằng tôi figured tôi muốn tạo ra một BaseRepositoryTest - như thế này:

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

Bây giờ, đối với mỗi đối tượng miền tôi sẽ phải thực hiện như thế nào để khởi tạo Kho lưu trữ và cách tạo một thực thể thử nghiệm, có vẻ công bằng, được cho là khác nhau ...

Tất cả những gì tôi phải làm bây giờ là viết thử nghiệm thực tế đúng không? Như thế này:

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

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

Điều này sẽ giúp tôi bắt đầu và thử nghiệm không thành công vì tôi sẽ thực hiện phương pháp không may mắn. Nhưng những người thử nghiệm (đã thử cả hai nunits GUI và runner thử nghiệm resharpers) chỉ cần bỏ qua bài kiểm tra cơ bản của tôi! Nó xuất hiện và tất cả - nhưng được báo cáo lại là Bị bỏ qua.

Vì vậy, tôi đã làm một chút đào ... NUnit có tài sản này trên TextFixtureAttribute cho phép bạn chỉ định những loại bạn đang thử nghiệm vì vậy tôi đã cố gắng đặt thuộc tính

[TestFixture(typeof(Foo))] 

Mở đầu tiên cơ sở và cũng là phiên bản Foo. Khi đặt trên phiên bản Foo nó vẫn chỉ bỏ qua các thử nghiệm từ các cơ sở, và khi tôi đặt nó trên cơ sở ... nó sẽ chuyển sang màu đỏ bởi vì các phương pháp ném ngoại lệ, mà sẽ là tốt ngoại trừ ngay cả khi tôi thực hiện thực tế trong FooTests, chúng vẫn không hoạt động (rõ ràng là bài kiểm tra Base cho thuộc tính TestFixture sẽ không bao giờ biết những lớp nào được kế thừa từ nó, vì vậy làm thế nào nó biết để tìm cách triển khai thực hiện).

Vì vậy, tôi phải làm gì? Tôi có thể làm bài kiểm tra trong lớp thử nghiệm cơ sở ảo và sau đó ghi đè lên nó trong FooBaseRepositoryTests, chỉ để gọi thực hiện từ cơ sở, mà là một giải pháp què mà tôi nghĩ ...

Còn gì nữa? Tui bỏ lỡ điều gì vậy? Xin hãy giúp đỡ, một người nào đó ... :)

Trả lời

1

Khi bạn đang sử dụng thuộc tính [TestFixture(typeof(Foo))] trên lớp lịch thi đấu để sử dụng cho các loại khác nhau; nó không phải là trừu tượng.

Nếu được sử dụng trong lịch thi đấu Foo, lớp đó phải là chung chung và không được nhập cho Foo.

Từ các tài liệu:

[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

Tôi thấy điểm của bạn, cảm ơn :) Nó không giải quyết vấn đề của tôi mặc dù, như AbstractFixtureBase chiến thắng ' t có thể có logic cho "AddWhenCallingAddsObjectToDatabase()", làm cho tôi viết việc thực hiện gần như giống nhau cho tất cả các đồ đạc có nguồn gốc ... –

+0

Tôi đang gắn cờ câu trả lời của bạn là đúng. Tôi đoán nó không thể với NUnit vì vậy điều này thực sự cho tôi thấy cách API hoạt động. –

0

Tôi chưa thử ví dụ của bạn nhưng bạn có thể thử nếu bạn đặt các thuộc tính TestFixture và Test trong cùng một lớp. Hãy thử đặt nó vào lớp cơ sở.

+0

Tôi đã thử rất nhiều kết hợp của TestFixture và thử nghiệm trên cả hai lớp học, tôi thành thật nghĩ rằng tôi đã thử tất cả;) –

2

Tôi có vấn đề này thời gian gần đây và tìm thấy một workaround khác nhau.Tôi có một giao diện IRepository generic mà tôi muốn để có thể thử nghiệm với nhiều triển khai, vì vậy tôi đã tạo ra một lớp cơ sở mà bỏ qua bản thân trong quá trình thiết lập, nhưng hành vi này sẽ bị thay bởi hậu duệ của nó:

[TestFixture] 
public class AbstractRepositoryTests 
{ 
    protected IRepository _repository; 

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

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

sau đó tôi ghi đè hành vi thiết lập trong hậu duệ của tôi để khởi tạo đối tượng kho lưu trữ thay vì bỏ qua tất cả các thử nghiệm:

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

Lớp dẫn xuất sẽ chạy tất cả các kiểm tra chính xác của nó. Phần chỉ hơi lộn xộn về điều này là lớp cơ sở tạo ra một loạt các bài kiểm tra "Bỏ qua", mà không phải là rất sạch sẽ.

+5

Bạn sẽ làm cho cuộc sống của bạn dễ dàng hơn nếu bạn thực sự tạo ra AbstractRepositoryTests như một lớp trừu tượng. Sau đó, chỉ các triển khai của nó sẽ được khởi tạo, và bạn sẽ không có vấn đề của lớp cơ sở tạo ra một loạt các kiểm tra bị bỏ qua. – kiprainey

Các vấn đề liên quan