Как протестировать два Java-класса дочерних классов, которые имеют одинаковое поведение, но разные детали реализации? [Дубликат]

Также как примечание:

CRTP может использоваться для реализации статического полиморфизма (который, как динамический полиморфизм, но без таблицы указателей виртуальных функций).

#pragma once
#include <iostream>
template <typename T>
class Base
{
    public:
        void method() {
            static_cast<T*>(this)->method();
        }
};

class Derived1 : public Base<Derived1>
{
    public:
        void method() {
            std::cout << "Derived1 method" << std::endl;
        }
};


class Derived2 : public Base<Derived2>
{
    public:
        void method() {
            std::cout << "Derived2 method" << std::endl;
        }
};


#include "crtp.h"
int main()
{
    Derived1 d1;
    Derived2 d2;
    d1.method();
    d2.method();
    return 0;
}

Выход был бы:

Derived1 method
Derived2 method
21
задан Shog9 25 June 2010 в 23:32
поделиться

5 ответов

Чтобы протестировать интерфейс с общими тестами независимо от реализации, вы можете использовать абстрактный тестовый пример, а затем создать конкретные экземпляры тестового примера для каждой реализации интерфейса.

Абстрактная (базовая) тестовый пример выполняет нейтральные для реализации тесты (т. е. проверяет договор интерфейса), в то время как конкретные тесты заботятся о создании экземпляра объекта для тестирования и выполняют любые тесты, специфичные для реализации.

19
ответ дан mdma 22 August 2018 в 06:23
поделиться

Может создавать методы, которые принимают параметр типа IMyInterface и имеют реальные методы тестирования, просто вызывая эти методы, проходящие в разных конкретных классах.

3
ответ дан Davy8 22 August 2018 в 06:23
поделиться

Если вы используете 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);
    }
}
0
ответ дан James 22 August 2018 в 06:23
поделиться

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

2
ответ дан Kathy Van Stone 22 August 2018 в 06:23
поделиться

Если вы хотите использовать те же тесты для разных исполнителей вашего интерфейса, используя 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();
    }
}
40
ответ дан Tim Lloyd 22 August 2018 в 06:23
поделиться
  • 1
    Это хороший пример правильного ответа. – Chetan 30 June 2010 в 17:58
  • 2
    +1 Хороший ответ! В настоящее время NUnit поддерживает общие тестовые классы, а атрибут TestFixture может использоваться для предоставления конкретных типов, которые будут использоваться при запуске теста. Я написал сообщение в блоге о том, как тестировать каждого исполнителя интерфейса, демонстрирующего эти функции. – Marjan Venema 28 March 2015 в 19:46
  • 3
    Элегантный и лаконичный ответ ... – Manas Kumar 5 June 2016 в 18:43
Другие вопросы по тегам:

Похожие вопросы: