Создание экземпляра класса доступа

В настоящее время я пишу структуру модульного тестирования, которая в конечном итоге должна запускать стандартные модульные тесты, написанные в Visual Studio. В настоящее время Framework неправильно работает с методами доступа. Рассмотрим следующий метод тестирования:

[TestMethod()]
public void TestMethod()
{
      ExampleMethods_Accessor target = null;
      target = new ExampleMethods_Accessor();
      target.SomeMethod();
}

В этом примере средство доступа было создано Visual Studio. Модульный тест отлично работает при запуске с использованием среды модульного тестирования Visual Studio. Однако я хотел бы вызвать TestMethod() из моего Framework. В строке «target = new ExampleMethods_Accessor()» возникает следующее исключение:

Инициализатор типа для "Proband.ExampleMethods_Accessor" вызвал исключение.

Внутреннее исключение:

Не удалось загрузить файл или сборку: пробанд, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = null...

Кто-нибудь знает, как Microsoft Unit Testing Framework вызывает модульные тесты? Я думал, что это может быть связано с отсутствующим объектом TestContext. В моем случае это "ноль". При запуске модульного теста в Visual Studio объект TestContext содержит много информации. Может быть, мне нужно правильно его инициализировать? Как его нужно инициализировать?

Спасибо за помощь, Кристиан

ИЗМЕНИТЬ:

Я продолжал экспериментировать с тем, как работают средства доступа. Я использовал ILSpy, чтобы увидеть, какой код генерируется в Proband_Accessor.dll. Оказывается, инструкция, вызывающая исключение:

SomeClass_Accessor.m_privateType = new PrivateType("Probant, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Probant.SomeClass");

Я изменил свой код модульного теста, чтобы он был таким (только для теста):

    [TestMethod()]
    [DeploymentItem("Proband.dll")]
    public void SomeMethodTest()
    {
        ExampleMethods_Accessor target = null;
        ExampleMethods c = null;

        try
        {
            Assembly.Load("Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); // this works fine
            PrivateType tx = new PrivateType(typeof(ExampleMethods)); // this works fine as well (also without loading the assembly)

            PrivateType t = new PrivateType("Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Proband.ExampleMethods"); // this causes the exception

            c = new ExampleMethods(); // this works fine
            target = new ExampleMethods_Accessor(); // this causes the exception as well
        }
        catch (Exception ex)
        {
            Console.WriteLine();
        }
        int actual;
        actual = target.SomeMethod();
    }

Я совершенно не понимаю, почему "new PrivateType("Proband, Version...." не работает. Есть идеи?


person Christian    schedule 10.10.2011    source источник
comment
Что такое сборка Proband и как вы пытались сделать ее доступной?   -  person Jon Skeet    schedule 10.10.2011
comment
что именно ты пишешь? похоже, что вы используете структуру MSTest из-за использования [TestMethod]. Вы пишете какой-то собственный тест runner?   -  person Adam Ralph    schedule 10.10.2011
comment
О, извините, что не объяснил: сборка пробанда - это та, которая содержит код, который нужно протестировать. ExampleMethods — это класс внутри сборки proband, который содержит приватные методы (SomeMethod).   -  person Christian    schedule 10.10.2011
comment
@Adam ralph - я пишу надстройку для платформы MSTest. Перед выполнением модульного теста я создаю мутации тестируемого кода и выполняю мутационное тестирование. Это работает очень хорошо, если вам не нужно использовать средства доступа.   -  person Christian    schedule 10.10.2011
comment
Интересный. Мутационное тестирование — это то, чего не хватает в инструментальном пространстве .NET. Вы видели msdn.microsoft.com/en-us/magazine/cc163619.aspx ?   -  person Adam Ralph    schedule 10.10.2011
comment
Да, я действительно читал эту статью. В моем фреймворке используются аналогичные методы сборки и разборки.   -  person Christian    schedule 10.10.2011


Ответы (3)


Мне удалось создать обходной путь для этой проблемы.

В свой AppDomain я добавляю AssemblyResolveEventHandler:

    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

Этот обработчик событий содержит следующий код:

    private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
    {
        if(args.Name == "Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
        {
            // resolving correct assembly of type under test
            return typeof(ExampleMethods).Assembly;
        }
        else
        {
            return null;
        }
    }

Теперь строка кода "target = new ExampleMethods_Accessor();" отлично работает и возвращает правильный объект доступа.

Я до сих пор не понимаю, почему сборка не может разрешиться автоматически.

Даже если очень маловероятно, что у кого-то будет такая же проблема: надеюсь, этот ответ кому-то поможет :)

person Christian    schedule 11.10.2011

Я не делаю ничего такого сложного, но у меня было:

  1. проект веб-приложения с использованием .NET 3.5
  2. Проект конфигурации с использованием .NET 3.5
  3. Тестовый проект с использованием .NET 3.5

Я получал такое же исключение BadImageFormat при попытке запустить модульный тест с использованием средства доступа.

Я нашел следующую ссылку:

http://connect.microsoft.com/VisualStudio/feedback/details/677203/даже-после-установки-vs2010-sp1-unit-tests-targeting-3-5-framework-fail-if-they-are-using-private-accessor#details

Второй обходной путь решил мою проблему. Я изменил тестовый проект на целевой .NET 4.0, и это сработало.

person xdhmoore    schedule 15.03.2012
comment
Спасибо за вклад, я попробую это с тестовой сборкой .NET 4.0. - person Christian; 16.03.2012

У меня была точно такая же проблема, потому что я удалил атрибут DeploymentItem из метода тестирования. Как только я добавил его снова, я больше не получал ошибку на машине сборки.

[TestMethod]
[DeploymentItem("FedImportServer.dll")]  // ** This is necessary for the build machine. **
public void SourceFileStillExistsAfterProcessingFails()

Примечание. Я никогда не получал ошибку при локальном запуске.

Это ошибка:

Test method FedImportTests.FedImportServiceHostTest.FileNoLongerExistsAfterSucessfulProcessing threw exception: System.TypeInitializationException: The type initializer for 'FedImportServer.Processing.FileProcessor_Accessor' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'FedImportServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

person Bob Horn    schedule 30.07.2012