Подтвердить что ты не робот

Можно ли использовать контекст логического вызова в unit test в VS 2010?

Возможно ли, чтобы этот тест не выдавал исключение? Похоже, что добавление любого класса, отличного от GACed, в контекст логического вызова вызывает исключение, которое должно быть выбрано в строке 2 теста.

Test 'TestProject1.UnitTest1.TestMethod1' не удалось: метод тестирования TestProject1.UnitTest1.TestMethod1 бросил исключение: System.Configuration.ConfigurationErrorsException: Произошла ошибка при загрузке файл конфигурации: Тип не разрешено для члена "TestProject1.Bar, TestProject1, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = нуль. --- > System.Runtime.Serialization.SerializationException: Тип не разрешен для члена" TestProject1.Bar, TestProject1, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = NULL".

namespace TestProject1 {
    [ Serializable]
    public class Bar {

    }

    [TestClass]
    public class UnitTest1 {
        [TestMethod]
        public void TestMethod1() {
            CallContext.LogicalSetData("foo", new Bar());
            ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None );
        }
    }
}

ПОЧЕМУ?!?!?

4b9b3361

Ответ 1

В принципе, это проблема с дизайном процесса, используемого для размещения тестового кода во время тестового прогона. Тесты запускаются в отдельном AppDomain из тестового хост-процесса по умолчанию AppDomain. Когда вызов выполняется из одного AppDomain в другой, контекст вызова должен быть десериализован в целевой AppDomain. В вашем случае ConfigurationManager.OpenExeConfiguration заканчивается вызовом AppDomain.get_Evidence. Это приводит к вызову из AppDomain, в котором размещаются тесты, по умолчанию для AppDomain.

Базовый каталог AppDomain по умолчанию - это место, где установлен исполняемый файл тестового хоста. По умолчанию это "% ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE" . В AppDomain, где размещаются тесты, используется базовый каталог места развертывания тестового запуска. По умолчанию это "<solutiondir> \TestResults\<testrun> \Out" . Таким образом, AppDomain, используемый для запуска тестов, может разрешать сериализованные типы, поскольку их сборки лежат в каталоге Out (независимо от того, они уже загружены в тестовый AppDomain, потому что этот код выполняется), в то время как AppDomain по умолчанию не может.

GACing сборок, содержащих сериализованные типы, работает, потому что GAC исследуется во время разрешения сборки. Это одно из возможных решений. Тем не менее, вам нужно будет установить их в GAC при каждом тестовом прогоне, и для этого требуются сильные имена и административные привилегии.

Другим возможным решением было бы скопировать сборки на путь исследования по умолчанию AppDomain. Это будет базовый каталог, указанный выше, и privatePath, перечисленные в QTAgent.exe.config или QTAgent32.exe.config(который запускается, зависит от того, используете ли вы 64-разрядную операционную систему и настройку платформы хостинга в тестовые настройки). Как и во всех частных путях обнаружения, эти каталоги должны быть подкаталогами базового каталога. Вы можете создать новый подкаталог с соответствующими разрешениями доступа, добавить имя каталога в privatePaths в файлах .exe.config, а затем скопировать сборки, содержащие сериализованные типы, в этот каталог во время установки теста. Это решение не потребует административных привилегий или сильного имени, если каталог, который вы копируете сборки, позволяет вам писать на него.

К сожалению, ни одно из этих решений не является идеальным, поскольку они могут ввести возможность несоответствия типов между кодом, запущенным в AppDomain тестов и AppDomain по умолчанию, если сборки не обновляются должным образом перед каждым испытательным прогоном. Правильное исправление потребуется от Microsoft (например, если тестовый хост-процесс автоматически исследует тестовый каталог развертывания, когда по умолчанию AppDomain должен разрешать типы). Я не работал над тестовыми инструментами, поэтому я не могу комментировать, что потребует реального исправления, учитывая детали реализации.

Изменить. Если вы выберете одно из этих "решений", вам также необходимо отключить процесс тестового хоста, чтобы оставаться в живых между тестовыми запусками. Это связано с тем, что AppDomain по умолчанию будет закрываться, а сборки, содержащие сериализованные типы, будут оставаться загруженными, не позволяя вам обновлять их при следующем тестовом прогоне. Опцией для управления этим является "Держать механизм выполнения тестов, запущенный между тестовыми запусками" в разделе "Инструменты → Параметры → " Тестирование "- > " Тестирование ".

Ответ 2

При использовании логического CallContext для хранения объектов реализуется соответствующая логика завершения (IDisposable) для очистки объектов, хранящихся в CallContext (например: CallContext.FreeNamedDataSlot)

Надеюсь, что это поможет,

Juanjo

Ответ 3

Эта проблема может быть решена, если Bar реализует MarshalByRefObject. Это позволяет ссылаться на класс в AppDomain, в котором работает тестовый бегун.

[ Serializable]
public class Bar : MarshalByRefObject {

}