Заглушка с помощью Ruby-on-Rails и MiniTest - PullRequest
0 голосов
/ 30 ноября 2018

Я пытаюсь понять, как работает заглушка с Rails и MiniTest.Я следовал простому примеру из документации MiniTest .Я застрял на очень простом примере:

require 'minitest/mock'
require "test_helper"

class TotoTest < ActiveSupport::TestCase

  class Clazz
    def foo
      "foo"
    end
  end

  test "Stubbing" do
    puts Clazz.new.foo # "foo" is well printed
    Clazz.stub :foo, "bar" do # ERROR HERE
      assert_equal "bar", Clazz.new.foo
    end
  end
end

При заглушке я получаю сообщение об ошибке foo.Полный журнал выполнения:

Testing started at 13:55 ...
[...]
Started

foo

Minitest::UnexpectedError: NameError: undefined method `foo' for class `TotoTest::Clazz'
    test/models/toto_test.rb:14:in `block in <class:TotoTest>'
test/models/toto_test.rb:14:in `block in <class:TotoTest>'
Finished in 0.52883s
1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

Process finished with exit code 0

Я не могу понять, почему мне говорят, что foo метод не существует, когда выполнение выполняется хорошо на линии раньше.

Чтоя скучаю?Почему это не работает?

Я даже попробовал альтернативу, используя макет:

require 'minitest/mock'
require "test_helper"

class TotoTest < ActiveSupport::TestCase

  class Clazz
    def foo
      "foo"
    end
  end

  test "Stubbing" do
    mock = Minitest::Mock.new
    def mock.foo
      "bar"
    end

    puts Clazz.new.foo
    Clazz.stub :foo, mock do
      assert_equal "bar", Clazz.new.foo
    end
  end
end

Результат тот же.Где я не прав?

РЕДАКТИРОВАТЬ: Вариант использования

Если быть более точным, я хотел бы заглушить API YouTube.Вызовы API YouTube реализованы в модуле.Модуль включен в контроллер.В системном тесте я хотел бы заменить реальный вызов этого API заглушкой, чтобы он не зависел от YouTube API.

1 Ответ

0 голосов
/ 30 ноября 2018

Вы используете метод класса вместо метода экземпляра:

Clazz.stub :foo, "bar"

Вы вызываете stub в экземпляре класса Class, на который ссылается константа Clazz.

Вы должны позвонить #stub на Clazz экземпляр:

clazz = Clazz.new
clazz.stub :foo, mock do
  assert_equal "bar", clazz.foo
end

Редактировать: Относительно варианта использования.Я думаю, что контроллер - это неправильное место для включения методов обработки внешнего API.Я бы предложил обернуть его в отдельный объект, затем вы можете заглушки этого объекта, например:

yt_mock = ... # mocking yt methods you want to use
YouTube.stub :new, yt_mock do
  # controler test
end

Вы также можете создать YouTube как класс, который принимает адаптеры и делегирует вызовы к ним - один адаптер будет использоватьнастоящий YT API, другой только предопределенные ответы.

...