Код Поблочного тестирования, который называет VirtualPathUtility. ToAbsolute

Непонятно, зачем вам нужен метакласс, , вероятно, нет . Но ради упражнения давайте рассмотрим, что это происходит.

Область действия функции Python определяется следующим образом

locals > closure > globals > builtins

Никогда не будет поиск функции в пространстве имен области, где она была вызвана. Обратите внимание, что в этом случае даже определение MyClass.__init__ не будет работать, так как методы класса должны обращаться к своему пространству имен класса через атрибуты.

class SomeClass:
    foo = 0
    def __init__(self):
        self.foo # works
        foo # raises NameError

В частности, это означает, что ваш метод init найдет fields в теле MyMeta.__new__, что является его закрытием.

Хотя, обратите внимание, что пространство имен класса передается в качестве четвертого аргумента методу MyMeta.__new__, здесь attr. Итак, вы можете найти Myclass.fields в attr['fields'] в MyMeta.__new__.

Пример

class MyMeta(type):
    def __new__(mcs, name, bases, attr):
        fields = {'foo': 0}

        def init(self, **kwargs):
            print('kwargs:', kwargs)
            print('MyMeta.__new__.fields:', fields)
            print('attr["fields"]:', attr['fields'])

        attr['__init__'] = init
        return type.__new__(mcs, name, bases, attr)


class Myclass(metaclass=MyMeta):
    fields = {'bar': 1}


r = {'baz': 2}
c = Myclass(**r)

Выход

kwargs: {'baz': 2}
MyMeta.__new__.fields: {'foo': 0}
attr["fields"]: {'bar': 1}
13
задан Heinzi 20 April 2017 в 14:20
поделиться

1 ответ

Статические классы и методы действительно тверды работать с в модульных тестах (который является одной причиной, почему я стараюсь избегать их). В этом случае я, вероятно, разработал бы обертку вокруг статического класса, содержа просто те методы, которые я использую. Я затем использовал бы свой класс обертки вместо реального класса. Класс обертки был бы создан так, чтобы было легко дразнить.

Пример (вид) использование RhinoMocks. Обратите внимание, что это использует внедрение зависимости для предоставления класса под тестом копия обертки. Если предоставленная обертка является пустой, она создает тот.

public class MyClass
{
     private VPU_Wrapper VPU { get; set; }

     public MyClass() : this(null) {}

     public MyClass( VPU_Wrapper vpu )
     {
         this.VPU = vpu ?? new VPU_Wrapper();
     }

     public string SomeMethod( string path )
     {
         return this.VPU.ToAbsolute( path );
     }
}

public class VPU_Wrapper
{
    public virtual string ToAbsolute( string path )
    {
         return VirtualPathUtility.ToAbsolute( path );
    }
}

[TestMethod]
public void SomeTest()
{
     string path = "~/path";
     string expected = "/app/path";

     var vpu = MockRepository.GenerateMock<VPU_Wrapper>();
     vpu.Expect( v => v.ToAbsolute( path) ).Return( expected );

     MyClass class = new MyClass( vpu );

     string actual = class.SomeMethod( path );

     Assert.AreEqual( expected, actual );

     vpu.VerifyAllExpectations();
}
8
ответ дан 1 December 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: