2015-10-22 2 views
1

Я создал систему приглашений пользователей в своем приложении Flask и хочу протестировать ее с помощью Python unittest. Я использую SendGrid для отправки писем. Как я могу остановить SendGrid от фактической отправки электронной почты во время теста? Я могу получить ссылку на приглашение пользователя и вставить ее в свой тест? Мой код ниже:Тестирование системы приглашения пользователя

# views.py 
@app.route('/add_user', methods=['GET', 'POST']) 
@login_required 
@groups_required(['site_admin']) 
def add_user(): 
    """ 
    Send invite email with token to invited user 
    """ 
    form = AddUserForm() 

    if form.validate_on_submit(): 

     # token serializer 
     ts = URLSafeTimedSerializer(app.config['SECRET_KEY']) 

     email = request.form['email'] 
     tenant_id = user.custom_data['tenant_id'] 

     # create token containing email and tenant_id 
     token = ts.dumps([email, tenant_id]) 

     # create url with token, e.g. /add_user_confirm/asdf-asd-fasdf 
     confirm_url = url_for(
      'add_user_confirm', 
      token=token, 
      _external=True) 

     try: 
      # sendgrid setup 
      sg = sendgrid.SendGridClient(
       app.config['SENDGRID_API_KEY'], 
       raise_errors=True 
      ) 

      # email setup 
      message = sendgrid.Mail(
       to=request.form['email'], 
       subject='Account Invitation', 
       html='You have been invited to set up an account on PhotogApp. Click here: ' + confirm_url, 
       from_email='[email protected]' 
      ) 

      # send email 
      status, msg = sg.send(message) 

      flash('Invite sent successfully.') 
      return render_template('dashboard/add_user_complete.html') 

     # catch and display SendGrid errors 
     except SendGridClientError as err: 
      flash(err.message.get('message')) 
     except SendGridServerError as err: 
      flash(err.message.get('message')) 
    return render_template('dashboard/add_user.html', form=form) 


@app.route('/add_user_confirm/<token>', methods=['GET', 'POST']) 
def add_user_confirm(token): 
    """ 
    Decode invite token and create new user account 
    """ 
    form = RegistrationForm() 
    decoded = None 
    try: 
     ts = URLSafeTimedSerializer(app.config['SECRET_KEY']) 
     decoded = ts.loads(token, max_age=86400) 
     email = decoded[0] 
    except: 
     abort(404) 

    if form.validate_on_submit(): 
     try: 
      tenant_id = decoded[1] 

      data = {} 
      data['email'] = email 
      data['password'] = request.form['password'] 

      # given_name and surname are required fields 
      data['given_name'] = 'Anonymous' 
      data['surname'] = 'Anonymous' 

      # set tenant id and site_admin status 
      data['custom_data'] = { 
       'tenant_id': tenant_id, 
       'site_admin': 'False' 
      } 

      # create account 
      account = User.create(**data) 

      # add user to tenant group 
      account.add_group(tenant_id) 

      # login user 
      login_user(account, remember=True) 

      # success redirect 
      return render_template('account/add_user_complete.html') 
     except StormpathError as err: 
      flash(err.message.get('message')) 

    elif request.method == 'POST': 
     flash("Passwords don't match.") 

    return render_template('account/add_user_setpassword.html', 
          form=form, 
          email=email) 

# tests.py 
def test_add_user(self): 
    resp = self.client.post('/add_user', data={ 
      'email': self.test_email 
     }, follow_redirects=True) 
assert 'User invitation sent' in resp.data 

ответ

1

Так что это довольно прекрасный случай для насмешек. Существенная идея насмешки заключается в том, что вы заменяете текущую функциональность (в этом случае отправляете электронное письмо) с прохождением через мир, сбоем, побочным эффектом.

If you're using Python 2.7 you'll have to download the mock third party package

В противном случае вы можете просто сказать

from unittest import mock 

In this particular case I'd suggest using mock.patch

# tests.py 
from unittest import mock 

@mock.patch("sg.send") 
def test_add_user(self, mocked_send): 
    mocked_send.return_value = None # Do nothing on send 
    resp = self.client.post('/add_user', data={ 
      'email': self.test_email 
     }, follow_redirects=True) 
assert 'User invitation sent' in resp.data 

Это сделает это так, что, когда sg.send называется это будет вызывать высмеивал функцию, а не реальный функция. Поскольку mocks пустые по умолчанию, не страшная отправка электронной почты.

ПРИМЕЧАНИЕ: SendGrid необходимо импортировать и в объем в вашем файле test.py.

+0

Это замечательно. Раньше я никогда не слышал об этом. Я пытаюсь заставить его работать, но я запускаюсь в «ImportError: здесь, где я настраиваю sg»: https://github.com/caseydm/photog/blob/master/project/tests/test_views.py#L63 – Casey

+0

У меня нет времени посмотреть на ваш код сегодня вечером, но я постараюсь запустить его завтра и отчитаться. Если я забуду, тыкай меня. – AlexLordThorsen

+0

В итоге я задал отдельный вопрос и получил отличный ответ. Благодаря! http://stackoverflow.com/questions/33311001/how-to-mock-a-sendgrid-method-in-python – Casey

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