2013-04-11 2 views
43

У меня есть базовый класс для моих тестов, составляющие следующим образом:MSTest ClassInitialize и наследование

[TestClass] 
public abstract class MyBaseTest 
{ 
    protected static string myField = ""; 

    [ClassInitialize] 
    public static void ClassInitialize(TestContext context) 
    { 
     // static field initialization 
     myField = "new value"; 
    } 
} 

Теперь я пытаюсь создать новый тест, который наследуется от основания, со следующей подписью:

[TestClass] 
public class MyTest : MyBaseTest 
{ 
    [TestMethod] 
    public void BaseMethod_ShouldHave_FieldInitialized() 
    { 
     Assert.IsTrue(myField == "new value"); 
    } 
} 

ClassInitialize никогда не вызывается ребенком тестов ... Что такое реальный и правильный способ использования инициализации теста с наследованием на MSTest?

+0

Дубликат (сквозные проблемы, которые просто так случиться, чтобы потребовать те же настройки для каждого тестового класса и метод испытания.): HTTP: //stackoverflow.com/questions/7322154/classinitialize-attribute-in-unit-test-based-class-not-called –

ответ

27

К сожалению, вы не можете достичь этого, потому что ClassInitializeAttribute Class не может быть унаследован.

Унаследованный атрибут может использоваться подклассами классов, которые его используют. Поскольку ClassInitializeAttribute не может быть унаследован, когда класс MyTest инициализирован, метод ClassInitialize из класса MyBaseTest не может быть вызван.

Попробуйте решить эту проблему другим способом. Менее эффективным способом является определение метода ClassInitialize в MyTest и просто вызов базового метода вместо дублирования кода.

+22

Я пробовал ваш подход, и он работает, но, честно говоря, Microsoft должна это исправить, потому что NUnit не имеет такого поведения , – Raffaeu

+0

Когда вы говорите, что класс ClassInitializeAttribute не может быть унаследован, ссылаетесь ли вы на класс, который является «запечатанным»? - это не должно влиять на то, как появляется атрибут при применении к унаследованному методу ... – binki

+0

Поскольку он не устанавливает атрибут AttributeUsageAttribute. Inherited' to 'false', он будет унаследован ... – binki

0

Мы знаем, что новый экземпляр класса построен для каждого [TestMethod] в классе по мере его запуска. Каждый раз, когда это происходит, будет вызываться конструктор без параметров. Не могли бы вы просто создать статическую переменную в базовом классе и проверить ее при запуске конструктора?

Это поможет вам не забыть поместить код инициализации в подкласс.

Не уверен, есть ли недостаток этого подхода ...

Как так:

public class TestBase 
{ 
    private static bool _isInitialized = false; 
    public TestBase() 
    { 
     if (!_isInitialized) 
     { 
      TestClassInitialize(); 
      _isInitialized = true; 
     } 
    } 

    public void TestClassInitialize() 
    { 
     // Do one-time init stuff 
    } 
} 
public class SalesOrderTotals_Test : TestBase 
{ 
    [TestMethod] 
    public void TotalsCalulateWhenThereIsNoSalesTax() 
    { 
    } 
    [TestMethod] 
    public void TotalsCalulateWhenThereIsSalesTax() 
    { 
    } 
} 
+2

Вы не знаете, t получить TestContext с этим решением. Это облом. – Visser

+0

Кроме того, у вас нет CleanUp – bubi

3

Потенциальный обходной путь, чтобы определить новый класс с AssemblyInitializeAttribute вместо этого. Она имеет различные масштабы, конечно, но для меня это отвечает моим потребностям

using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace MyTests 
{ 
    [TestClass] 
    public sealed class TestAssemblyInitialize 
    { 
    [AssemblyInitialize] 
    public static void Initialize(TestContext context) 
    { 
     ... 
    } 
    } 
} 
+0

Это то, что я тоже делал, но мне любопытно; почему ваш класс базового теста «запечатан»? Разве это не мешает вам наследовать этот класс и делать именно то, что вы намеревались сделать? –

+0

Я не использую его для наследования. Все мои настоящие классы тестов проистекают из другого базового класса.Этот класс предназначен исключительно для метода AssemblyInitialize. Это просто дизайнерское решение, которое я сделал, чтобы разделить вещи. –

Смежные вопросы