Модульные тесты, которые наследуются от типа, который использует дженерики - PullRequest
1 голос
/ 16 июля 2009

У меня есть интерфейс с обобщениями, который реализован некоторыми классами. Для каждого из этих классов есть прокси-класс, который также реализует интерфейс. Примерно такой код:

public interface ISomeInterface<T>
{
    T SomeProperty
    {
        get;
    }

    T SomeAction();
}

public interface IClassA : ISomeInterface<string>
{
    void Action();
}


public class ClassA : IClassA
{
    // Code goes here
}

public class ClassAProxy : IClassA
{
    // Code goes here
}

Код модульных тестов. Я бы хотел выглядеть примерно так:

public abstract class ISomeInterfaceTests<T>
{
    [TestMethod()]
    public void SomePropertyTest()
    {
        ISomeInterface<T> target;
        ISomeInterface<T> oracle;
        this.CreateInstance(out target, out oracle);

        Assert.AreEqual(oracle.SomeProperty, target.SomeProperty);
    }

    [TestMethod()]
    public void SomeActionTest()
    {
        ISomeInterface<T> target;
        ISomeInterface<T> oracle;
        this.CreateInstance(out target, out oracle);

        T oracleValue = oracle.SomeAction();
        T targetValue = target.SomeAction();

        Assert.AreEqual(oracleValue, targetValue);
    }

    // More tests

    protected abstract void CreateInstance(out ISomeInterface<T> target, out ISomeInterface<T> oracle);
}

[TestClass()]
public class ClassAProxyTests : ISomeInterfaceTests<string>
{
    // ClassAProxy specific tests

    protected override void CreateInstance(out ISomeInterface<string> target, out ISomeInterface<string> oracle)
    {
        // Create target as ClassAProxy here and oracle as ClassA
    }
}

Но это дает ошибку: UTA002: атрибут TestClass не может быть определен в универсальном классе ISomeInterfaceTests .

Есть ли хороший обходной путь к этому? В настоящее время лучшее решение, которое я могу придумать, это иметь метод в ClassAProxyTests, который вызывает различные методы тестирования в ISomeInterfaceTests . Однако у этого подхода есть несколько проблем:

  • Это нужно сделать вручную для каждого теста, реализующего ISomeInterfaceTests .
  • Если один из методов приведет к ошибочному утверждению, остальные методы не будут выполнены.
  • Вы не можете использовать атрибут ExpectedException и должны обернуть необходимый код в операторах try catch.

но, увы, лучшее решение ускользает от меня.

Ответы [ 2 ]

1 голос
/ 16 июля 2009

Похоже, вам нужно использовать GenericTestFixture NUnit 2.5. Эта функция позволяет поместить атрибут [TestFixture] в общий класс, а затем указать, какие специализации применяются к тестовому приспособлению.

Ваш основной тестовый прибор будет выглядеть следующим образом (и вы также сможете удалить некоторые интерфейсы):

[TestFixture(typeof(string))]
public class ClassAProxyTests<T> : ISomeInterfaceTests<T> where T: class
{
    // Add ISomeInterfaceTests<T> methods here.
    // ISomeInterfaceTests may no longer be required as the abstraction is defined in ClassAProxyTests.

    // ClassAProxy specific tests

    protected override void CreateInstance(out ISomeInterface<T> target, out ISomeInterface<string> oracle)
    {
        // Create target as ClassAProxy here and oracle as ClassA
    }
}
0 голосов
/ 16 июля 2009

Единственная причина, по которой у вас есть родительский класс, - это создание экземпляров вашего интерфейса, да?

Используйте взамен MOQ .

Редактировать:

Не совсем.Класс ISomeInterfaceTests используется для проверки функциональности прокси, реализующих интерфейс ISomeInterface - он проверяет прокси на предмет объектов, для которых они являются прокси (оракул). - Cornelius

Хм ... это звучит как интеграционный тест.Ваши объекты оракула как-то читаются из базы данных, или вы издеваетесь над ними, как и должно быть?Во всяком случае, я поддерживаю Moq, чтобы получить ваши экземпляры и тестирование насмешек против интеграции в целом.

Но меня поражает, что ваш подход к обобщению ваших тестов может быть проблемой.Возможно, другой подход?Попробуйте это на:

public static class GenericISomeInterfaceTests
{
    public static void SomePropertyTest<T>(ISomeInterface<T> target, ISomeInterface<T> oracle)
    {

        Assert.AreEqual(oracle.SomeProperty, target.SomeProperty);
    }

    public static void SomeActionTest<T>(ISomeInterface<T> target, ISomeInterface<T> oracle)
    {

        T oracleValue = oracle.SomeAction();
        T targetValue = target.SomeAction();

        Assert.AreEqual(oracleValue, targetValue);
    }

    // More tests
}

[TestClass()]
public class ClassAProxyTests
{
    [TestMethod]
    public void SomePropertyStringTest()
    {
        // set up instances (using MOQ, or whatever) with the string generic type. 
        // Call them target and oracle

        // then call your generic test methods
        GenericISomeInterfaceTests.SomePropertyTest<string>(target, oracle);
    }

    [TestMethod]
    public void SomeActionStringTest()
    {
        // set up instances (using MOQ, or whatever) with the string generic type. 
        // Call them target and oracle

        // then call your generic test methods
        GenericISomeInterfaceTests.SomeActionTest<string>(target, oracle);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...