我有多個實現相同接口的類,應該如何編寫單元測試來驗證每個類是否正確地實現了接口,並將代碼重複保持在最小值(DRY)?我應該如何爲一個接口的多個實現編寫單元測試,同時堅持DRY?
作爲我的意思的一個例子,以下是一個非常基本的庫,其中包含兩個實現IDeleter
:Deleter1
和Deleter2
。兩者均通過在其關聯的IRepository
上調用Delete
來實施方法Delete
。
using Microsoft.Practices.Unity;
namespace TestMultiple
{
public interface IRepository
{
void Delete(string id);
}
public abstract class Baseclass
{
protected abstract IRepository GenericRepository { get; }
public void Delete(string id)
{
GenericRepository.Delete(id);
}
}
public interface IDeleter
{
void Delete(string id);
}
public interface IRepository1 : IRepository
{
}
public abstract class RepositoryBase
{
public void Delete(string id)
{
}
}
public class Repository1 : RepositoryBase, IRepository1
{
}
public class Deleter1 : Baseclass, IDeleter
{
protected override IRepository GenericRepository { get { return Repository; } }
[Dependency]
public IRepository1 Repository { get; set; }
}
public interface IRepository2 : IRepository
{
}
public class Repository2 : RepositoryBase, IRepository2
{
}
public class Deleter2 : Baseclass, IDeleter
{
protected override IRepository GenericRepository { get { return Repository; } }
[Dependency]
public IRepository2 Repository { get; set; }
}
}
對於這兩個類,Deleter1
和Deleter2
,我已經寫兩個相應的單元測試類如示於下段。測試檢查相同的行爲,即在基礎存儲庫上調用Delete
。是否有更好的方法來實現IDeleter
所有實現的相同測試?例如,我應該編寫一個包含通用測試方法的基類,例如TestDelete
,對於TestDeleter1
和TestDeleter2
?
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity;
using Moq;
namespace TestMultiple.Tests
{
[TestClass]
public class TestDeleter1
{
[TestMethod]
public void TestDelete()
{
var mockRepo = new Mock<IRepository1>();
var container = new UnityContainer().RegisterInstance<IRepository1>(mockRepo.Object);
var deleter = container.Resolve<Deleter1>();
deleter.Delete("id");
mockRepo.Verify(r => r.Delete("id"));
}
}
[TestClass]
public class TestDeleter2
{
[TestMethod]
public void TestDelete()
{
var mockRepo = new Mock<IRepository2>();
var container = new UnityContainer().RegisterInstance<IRepository2>(mockRepo.Object);
var deleter = container.Resolve<Deleter2>();
deleter.Delete("id");
mockRepo.Verify(r => r.Delete("id"));
}
}
}
編輯: 隨意提的單元測試框架,可以幫助解決這類問題,雖然我的偏好是NUnit的。
繼承?創建一個內部具有所有通用性的基類,然後從每個需要測試的具體類型中派生出來(不同的測試框架可能會使這變得更容易或不會) –
(而且要清楚的是,我建議在測試類中繼承,而不是必須在實現中) –
@Damien_The_Unbeliever這是我考慮的一種方法。我一直在用Python做這件事,但用那種語言,我認爲存在一些問題(測試基礎類,而不是每個IIRC子類)。你介意把你的建議寫成答案嗎? – aknuds1