Как вы unit test интерфейс?
Например, существует интерфейс IMyInterface
, и три класса поддерживают этот интерфейс:
class A : IMyInterface
{
}
class B : IMyInterface
{
}
class C : IMyInterface
{
}
Проще всего я мог бы написать три тестовых класса: ATest, BTest, CTest и протестировать их отдельно. Однако, поскольку они поддерживают один и тот же интерфейс, большинство тестовых кодов будет одинаковым, его трудно поддерживать. Как я могу использовать простой и простой способ протестировать интерфейс, поддерживаемый разными классами?
(ранее заданный на форумах MSDN)
Ответы
Ответ 1
Чтобы протестировать интерфейс с общими тестами независимо от реализации, вы можете использовать абстрактный тестовый пример, а затем создать конкретные экземпляры тестового примера для каждой реализации интерфейса.
Исходный (базовый) тестовый пример выполняет нейтральные с реализацией тесты (т.е. проверяет контракт на интерфейс), в то время как конкретные тесты заботятся о создании экземпляра объекта для тестирования и выполняют любые тесты, специфичные для реализации.
Ответ 2
Если вы хотите использовать те же тесты для разных исполнителей вашего интерфейса, используя NUnit в качестве примера:
public interface IMyInterface {}
class A : IMyInterface { }
class B : IMyInterface { }
class C : IMyInterface { }
public abstract class BaseTest
{
protected abstract IMyInterface CreateInstance();
[Test]
public void Test1()
{
IMyInterface instance = CreateInstance();
//Do some testing on the instance...
}
//And some more tests.
}
[TestFixture]
public class ClassATests : BaseTest
{
protected override IMyInterface CreateInstance()
{
return new A();
}
[Test]
public void TestCaseJustForA()
{
IMyInterface instance = CreateInstance();
//Do some testing on the instance...
}
}
[TestFixture]
public class ClassBTests : BaseTest
{
protected override IMyInterface CreateInstance()
{
return new B();
}
}
[TestFixture]
public class ClassCTests : BaseTest
{
protected override IMyInterface CreateInstance()
{
return new C();
}
}
Ответ 3
Может создавать методы, которые принимают параметр типа IMyInterface и имеют реальные методы тестирования, просто вызывая эти методы, проходящие в разных конкретных классах.
Ответ 4
Вы не тестируете интерфейс напрямую, но можете написать абстрактный класс, который проверяет контракт, который должен распространяться на конкретную реализацию. Тест конкретного класса затем расширил абстрактный класс
Ответ 5
Если вы используете NUnit, вы можете использовать Grensesnitt:
public interface ICanAdd {
int Add(int i, int j); //dont ask me why you want different adders
}
public class winefoo : ICanAdd {
public int Add(int i, int j)
{
return i + j;
}
}
interface winebar : ICanAdd {
void FooBar() ;
}
public class Adder1 : winebar {
public int Add(int i, int j) {
return i + j;
}
public void FooBar() {}
}
public class Adder2 : ICanAdd {
public int Add(int i, int j) {
return (i + 12) + (j - 12 ); //yeeeeeaaaah
}
}
[InterfaceSpecification]
public class WithOtherPlugins : AppliesToAll<ICanAdd>
{
[TestCase(1, 2, 3)]
[TestCase(-1, 2, 1)]
[TestCase(0, 0, 0)]
public void CanAddOrSomething(int x, int y, int r)
{
Assert.AreEqual(subject.Add(x, y), r);
}
[TestCase(1, 2, Result = 3)]
[TestCase(-1, 2, Result = 1)]
[TestCase(0, 0, Result = 0)]
public int CannAddOrSomethingWithReturn(int x, int y) {
return subject.Add(x, y);
}
}