2014-12-10 3 views
6

Я работаю над проектом django, находящимся где-то там, где есть класс, определенный следующим образом;AttributeError: невозможно установить атрибут

from django.http import HttpResponse 

class Response(HttpResponse): 
    def __init__(self, template='', calling_context='' status=None): 
     self.template = template 
     self.calling_context = calling_context 
     HttpResponse.__init__(self, get_template(template).render(calling_context), status) 

и этот класс используется в представлениях следующим

def some_view(request): 
    #do some stuff 
    return Response('some_template.html', RequestContext(request, {'some keys': 'some values'})) 

этот класс был в основном создан для того, чтобы они могли использовать его для выполнения утверждения в единичных испытаний .ie они django.test не используется .Client, чтобы проверить взгляды, а они создают макет запрос и передать, чтобы посмотреть (называя вид как вызываемый) в тестах следующего

def test_for_some_view(self): 
    mock_request = create_a_mock_request() 
    #call the view, as a function 
    response = some_view(mock_request) #returns an instance of the response class above 
    self.assertEquals('some_template.html', response.template) 
    self.assertEquals({}, response.context) 

Проблема заключается в том, что половина пути т hrough тестового набора (довольно огромный набора тестов), некоторые тесты начинают взрывать при выполнении

return Response('some_template.html', RequestContext(request, {'some keys': 'some values'})) 

и трассировки стека является

self.template = template 
AttributeError: can't set attribute 

полный стек след выглядит что-то вроде

====================================================================== 
ERROR: test_should_list_all_users_for_that_specific_sales_office 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
File "/Users/austiine/Projects/mped/console/metrics/tests/unit/views/sales_office_views_test.py", line 106, in test_should_list_all_users_for_that_specific_sales_office 
    response = show(request, sales_office_id=sales_office.id) 
File "/Users/austiine/Projects/mped/console/metrics/views/sales_office_views.py", line 63, in show 
    "sales_office_users": sales_office_users})) 
File "/Users/austiine/Projects/mped/console/metrics/utils/response.py", line 9, in __init__ 
    self.template = template 
    AttributeError: can't set attribute 

фактический тест потерпеть неудачу,

def test_should_list_all_users_for_that_specific_sales_office(self): 
    user_company = CompanyFactory.create() 
    request = self.mock_request(user_company) 
    #some other stuff 

    #calling the view 
    response = show(request, sales_office_id=sales_office.id) 
    self.assertIn(user, response.calling_context["sales_office_users"]) 
    self.assertNotIn(user2, response.calling_context["sales_office_users"]) 

код для представления шоу

def show(request, sales_office_id): 
    user = request.user 
    sales_office = [] 
    sales_office_users = [] 
    associated_market_names = [] 
    try: 
     sales_office = SalesOffice.objects.get(id=sales_office_id) 
     sales_office_users = User.objects.filter(userprofile__sales_office=sales_office) 
     associated_market_names = Market.objects.filter(id__in=   (sales_office.associated_markets.all())).values_list("name", flat=True) 
     if user.groups.all()[0].name == UserProfile.COMPANY_AO: 
      associated_market_names = [market.name for market in sales_office.get_sales_office_user_specific_markets(user)] 
     except: 
      pass 
    return Response("sales_office/show.html", RequestContext(request, {'keys': 'values'})) 
+0

Можете ли вы показать нам сообщение об ошибке трассировки? –

+0

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

+0

. Попробуйте напечатать тип (шаблон) перед собой .template = и сообщить мне информацию о печати. –

ответ

0

Похоже, что вы не используете self.template в Response классе. Попробуйте так:

class Response(HttpResponse): 
    def __init__(self, template='', calling_context='' status=None): 
     HttpResponse.__init__(self, get_template(template).render(calling_context), status) 
+0

yes self.template не используется внутри класса Response, его используется в тестах для утверждений вроде этого ; self.assertEquals ('some_template.html', response.template) то же самое с вызовом_context – austiine

+0

весь класс ответа существует для использования в тестах – austiine

+0

@austiine Итак, после удаления двух строк была ли та же ошибка? –

0

Я посмотрел Джанго исходный код, я понятия не имею, где template или templates атрибут приходят из в HttpResponse. Но я могу предложить вам изменить свой тестовый подход и перейти на рамки mock. Вы можете переписать тест, как:

@patch("qualified_path_of_response_module.response.Response", spec=Response) 
def test_should_list_all_users_for_that_specific_sales_office(self,mock_resp): 
    user_company = CompanyFactory.create() 
    request = self.mock_request(user_company) 
    #some other stuff 

    #calling the view 
    response = show(request, sales_office_id=sales_office.id) 
    self.assertTrue(mock_resp.called) 
    context = mock_resp.call_args[0][2] 
    self.assertIn(user, context["sales_office_users"]) 
    self.assertNotIn(user2, context["sales_office_users"]) 

@patch декоратор заменить Response() класс по MagicMock() и передать его в качестве метода испытания mock_resp переменной. Вы также можете использовать patch в качестве менеджера контекста по конструкции with, но декораторы - это более чистый способ сделать это. Я не знаю, является ли Response просто классом-заглушкой для тестирования, но в этом случае вы можете напрямую установить HttpResponce, но это зависит от вашего кода.

Информацию о call_argshere. Возможно, вам нужно использовать атрибут spec, потому что django делает некоторую проверку типов ... но попробуйте с ним и без него (я не эксперт по django). Исследуйте структуру mock: это даст вам множество мощных инструментов для простых тестов.

17

В этом ответе не рассматриваются особенности этого вопроса, но объясняется основная проблема. Это конкретное исключение «AttributeError: невозможно установить атрибут» увеличивается (см. source), когда атрибут, который вы пытаетесь изменить, на самом деле является property, у которого нет setter. Если у вас есть доступ к коду библиотеки, добавление сеттера решит проблему.

EDIT: обновленная исходная ссылка на новое место в коде.

+2

Я полагаю, это нужно считать достижением, получив отрицательный результат, а все остальные равны нулю. Я «абсолютно» лучше. :) – yoniLavi

+1

ссылка «источник» - 404, но в текущем коде я нашел свойства [здесь как python] (https://github.com/python/cpython/blob/5ff7132313eb651107b179d20218dfe5d4e47f13/Objects/descrobject.c#L1278), или как [фактический код C] (https://github.com/python/cpython/blob/5ff7132313eb651107b179d20218dfe5d4e47f13/Objects/descrobject.c#L1415) – luckydonald

+0

Возможно ли иметь свойство без сеттера? –

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