Методы юнит-тестирования, содержащие операторы using

Мне интересно, могут ли операторы Unittesting и using действительно идти рука об руку, поскольку нет способа высмеять одноразовый объект, созданный в операторе using. Как я смогу эффективно протестировать метод, содержащий следующую инструкцию using?

public void MyMethod ()
{
   using (MyDisposableClass disp = new MyDisposableClass ())
   {
       ...
   }
}

Использование операторов просто запрещено при юнит-тестировании?

Любые комментарии приветствуются.

11.12.2008 10:22:09
хороший вопрос альтернативы, о которых я могу думать, - это больше работы, чем оригинал.
Gishu 11.12.2008 10:48:48
4 ОТВЕТА

Нет, использование утверждений, безусловно, не запрещено. Но что на самом деле делает MyDisposableClass? Меня поражает, что дело не в том, что оператор using является проблемой, а в том, как метод создает новый объект, который вы хотите смоделировать - вот в чем проблема.

Вам действительно нужно издеваться над MyDisposableClass? Можно ли передать его в MyMethod вместо создания внутри него? Как всегда, хитрость заключается в том, чтобы понять, как подключиться к процессу и внедрить свои собственные объекты, когда вам нужно ...

4
11.12.2008 10:28:15
MyDisposableClass - это действительно адаптер для внешней системы, который мне нужен для Connect (), Login () и LogOut () при утилизации. Если я отправляю его как параметр, я сталкиваюсь с проблемой в родительском методе, верно?
Fadeproof 11.12.2008 11:09:23
Конечно, что-то нужно, чтобы создать это. Вам в основном нужно разработать лучший крючок для этого. К сожалению, трудно сказать вам точно, куда вводить объект, не зная больше о вашей системе, чем у нас, вероятно, есть время, чтобы увидеть здесь :(
Jon Skeet 11.12.2008 11:24:44

Использование фабричного шаблона и / или шаблона внедрения зависимостей значительно упростит способ, которым вы будете использовать методы модульного тестирования, которые создают свои собственные ресурсы.

Вот хорошее прочтение на эту тему:

1
11.12.2008 10:42:37

Поскольку вы хотите издеваться над классом ресурса, я предполагаю, что у вас уже есть

interface IResource : IDisposable
{
        void DoSomething();
}

class DisposableResource : IResource
{
    public void Dispose()       {  Console.WriteLine("That's it. I'm outta here!");  }
    public void  DoSomething()  {  Console.WriteLine("Hard work this");  }
}

Чтобы иметь возможность вводить объект, вам нужен шов .. т.е. GetResource ()

class MyClass
{
    protected virtual IResource GetResource()
    {
        return new DisposableResource();
    }
    public void MyMethod1()
    {
        using (IResource r = GetResource())
        {
            r.DoSomething();
        }
    }
}

В вашем тестовом коде просто создайте подкласс и переопределите GetResource (), чтобы вернуть макет.

class MySubClassForTest : MyClass
{
    protected override IResource GetResource()
    {
        return new MockResource();
    }
}
class MockResource : IResource    // or use a mock framework to create one
{
    public void  DoSomething()        { Console.WriteLine("Me work?"); }
    public void  Dispose()            { Console.WriteLine("Disposed Mock!"); }
}

Вот и все.

 MyClass obj = new MyClass();           // production code
 obj.MyMethod1();

 obj = new MySubClassForTest();         // test code
 obj.MyMethod1();
3
11.12.2008 14:29:03

TypeMock позволит вам посмеяться над этим. Он работает, изменяя IL на лету и, таким образом, не имеет проблем с дразнить вещи, которые вы иначе не можете издеваться.

Но даже с TypeMock вы все равно должны взглянуть на то, что Jon Skeet и Pop Catalin говорят выше. Ваш код будет легче поддерживать, если вы попытаетесь уменьшить количество зависимостей.

1
11.12.2008 11:14:59