Mock
От: Tem_2000  
Дата: 22.09.08 13:07
Оценка:
Доброе время суток.
Что такое Mock и для чего это надо — теорию я понял.
Но вот разбирая пример с NUnitForms

public interface IAppModel
  {
        int GetData();
  }

public class AppModel : IAppModel
  {
    private int data;

    public AppModel()
    {
      data = 0;
    }    
    public int GetData()
    {
      return data;
    }
  }

И вот сам тест

[TestFixture]
  public class ControllerTest
  {
    private int TestValue = 2;
    private string TestValueString = "2";

    private Mock model = null;    

    [SetUp]
    public void Setup()
    {
            model = new DynamicMock( typeof(IAppModel) );
    }
    
    [Test]
    public void Data()
    {
      model.ExpectAndReturn( "GetData", TestValue );
      Assert.AreEqual( TestValueString, controller.GetData() );
      model.Verify();
    }

  }

Кто нить может на пальцах объяснить, че мы тут тестируем, что мы делаем, и самое главное, зачем, и что нам это дает.


И еще попутно вопрос, Mock-ки создаются на интерфейсы, или можно создавать на любой класс?

Благодарбю всем откликнувшимся.
Re: Mock
От: Lloyd Россия  
Дата: 22.09.08 13:12
Оценка:
Здравствуйте, Tem_2000, Вы писали:

T_>Кто нить может на пальцах объяснить, че мы тут тестируем, что мы делаем, и самое главное,


Мы убеждаемся, что контроллер, если ему на вход подать корректные данные, на выходе вернет то, что мы ожидаем.

T_>зачем, и что нам это дает.


Если в резултате как-то изменений в коде контроллера тест сломается, мы сможем быстро и легоко локализовать ошибку

T_>И еще попутно вопрос, Mock-ки создаются на интерфейсы, или можно создавать на любой класс?


Зависит от библиотеки генерайии моков, которая используется. Некоторые позволяют чуть ли не статические методы подменять.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[2]: Mock
От: Tem_2000  
Дата: 22.09.08 15:28
Оценка:
Хочу уточнить, что я все правильно понимаю.
model.ExpectAndReturn( "GetData", TestValue );

это значит, что любой метод "GetData" будет заменен заглушкой и вернет значение, переданное в TestValue , или я ошибаюсь?
Re[3]: Mock
От: Lloyd Россия  
Дата: 22.09.08 15:33
Оценка: 3 (1)
Здравствуйте, Tem_2000, Вы писали:

T_>Хочу уточнить, что я все правильно понимаю.

T_>
T_>model.ExpectAndReturn( "GetData", TestValue );
T_>

T_>это значит, что любой метод "GetData" будет заменен заглушкой и вернет значение, переданное в TestValue , или я ошибаюсь?

не совсем. заглушками будет заменены все методы. а вот GetData при вызове вернет TestValue
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[3]: Mock
От: Time Россия  
Дата: 22.09.08 16:22
Оценка:
Здравствуйте, Tem_2000, Вы писали:

T_>Хочу уточнить, что я все правильно понимаю.

T_>
T_>model.ExpectAndReturn( "GetData", TestValue );
T_>

T_>это значит, что любой метод "GetData" будет заменен заглушкой и вернет значение, переданное в TestValue , или я ошибаюсь?

В данном случае, model это mock от IAppData, соотвесвенно это будет поддельная реализация этого интерфейса которая при вызове GetData вернёт TestValue, это для того чтобы Вы её сами не писали, например так:

[с#]
public class MockAppData : IAppData
{
private String _testValue;

public MockAppData(String TestValue)
{
_testValue = TestValue;
}

public String GetData()
{
return _testValue;
}
}
[/c#]

Mock библиотеки предназначены для быстрого создания поддельного окружения какого либо класса. Т.е. вы хотие протестирвоать класс А который взаимодействует с B,C... для создания B,C и получения одного состояния Вам прийдется пройти не малый путь инициализации каждого, последовательности вызовов, а тут просто создаёте их поддельные реализации и передаёте в А.
... << RSDN@Home 1 alpha 4 rev. 0>>
Re[4]: Mock
От: Flea  
Дата: 23.09.08 11:22
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>не совсем. заглушками будет заменены все методы. а вот GetData при вызове вернет TestValue

А как сделать, чтоб оригинальный метод при этом не вызывался?
Re[5]: Mock
От: Time Россия  
Дата: 23.09.08 13:19
Оценка:
Здравствуйте, Flea, Вы писали:

F>Здравствуйте, Lloyd, Вы писали:


L>>не совсем. заглушками будет заменены все методы. а вот GetData при вызове вернет TestValue

F>А как сделать, чтоб оригинальный метод при этом не вызывался?

Оригинальный это какой? AppModel.GetData? Он и так не будет вызываться, будет вызываться Mock реализация IAppModel.GetData.
... << RSDN@Home 1 alpha 4 rev. 0>>
Re[6]: Mock
От: Flea  
Дата: 23.09.08 13:42
Оценка:
Здравствуйте, Time, Вы писали:
Я тогда лучше свой пример приведу.
Есть такие классы:

public class Controller
{
        ...
        public bool IsTrue()
        {
            bool istrue = true;

            ...

            if (Condition)
            {
                using (TheForm form = new TheForm())
                {
                    form.ShowDialog(null, arg);
                }
            }

            return istrue;
        }
}

public class TheForm : Form
{
        public DialogResult ShowDialog(IWin32Window owner, MyType arg)
        {
            ...
            return this.ShowDialog(owner);
        }

}

Для этой функции надо написать тест так, чтоб вместо того, чтоб вызывать ShowDialog, просто возвращался DialogResult.
Пробую такой код:
        [Test]
        public void Controller_IsTrue()
        {
            Controller cont = new Controller();
            ...
            TheForm form = mocker.DynamicMock<TheForm>();
            Expect.Call(form.ShowDialog(null, null)).Return(DialogResult.OK);
            LastCall.IgnoreArguments();
            mocker.ReplayAll();

            bool res = cont.IsTrue();
            Assert.IsFalse(res);
        }

При этом ShowDialog вызывается и форма появляется. Если ее закрыть, тест проходит
Вроде бы по смыслу все, как в первом примере...
PS: используется Rhino mock
Re[7]: Mock
От: Time Россия  
Дата: 23.09.08 15:03
Оценка:
Здравствуйте, Flea, Вы писали:

F>Здравствуйте, Time, Вы писали:

F>Я тогда лучше свой пример приведу.
F>Есть такие классы:

F>
F>public class Controller
F>{
F>        ...
F>        public bool IsTrue()
F>        {
F>            bool istrue = true;

F>            ...

F>            if (Condition)
F>            {
F>                using (TheForm form = new TheForm())
F>                {
F>                    form.ShowDialog(null, arg);
F>                }
F>            }

F>            return istrue;
F>        }
F>}

F>public class TheForm : Form
F>{
F>        public DialogResult ShowDialog(IWin32Window owner, MyType arg)
F>        {
F>            ...
F>            return this.ShowDialog(owner);
F>        }

F>}
F>

F>Для этой функции надо написать тест так, чтоб вместо того, чтоб вызывать ShowDialog, просто возвращался DialogResult.
F>Пробую такой код:
F>
F>        [Test]
F>        public void Controller_IsTrue()
F>        {
F>            Controller cont = new Controller();
F>            ...
F>            TheForm form = mocker.DynamicMock<TheForm>();
F>            Expect.Call(form.ShowDialog(null, null)).Return(DialogResult.OK);
F>            LastCall.IgnoreArguments();
F>            mocker.ReplayAll();

F>            bool res = cont.IsTrue();
F>            Assert.IsFalse(res);
F>        }

F>

F>При этом ShowDialog вызывается и форма появляется. Если ее закрыть, тест проходит
F>Вроде бы по смыслу все, как в первом примере...
F>PS: используется Rhino mock

Всё дело в том что Вы пытаетесь поделать реализацию, вместо интерфейса. здесь. Для Вашего примера надо сделать так (обратите внимание на выделенное жирным):
F>
F>public class Controller
F>{
F>        ...
F>        public bool IsTrue()
F>        {
F>            bool istrue = true;

F>            ...

F>            if (Condition)
F>            {
F>                using (ITheForm form = new TheForm())
F>                {
F>                    form.ShowDialog(null, arg);
F>                }
F>            }

F>            return istrue;
F>        }
F>}

public interface ITheForm
{
DialogResult ShowDialog(IWin32Window owner, MyType arg);
}

F>public class TheForm : Form, ITheForm
F>{
F>        public DialogResult ShowDialog(IWin32Window owner, MyType arg)
F>        {
F>            ...
F>            return this.ShowDialog(owner);
F>        }

F>}
F>

F>Для этой функции надо написать тест так, чтоб вместо того, чтоб вызывать ShowDialog, просто возвращался DialogResult.
F>Пробую такой код:
F>
F>        [Test]
F>        public void Controller_IsTrue()
F>        {
F>            Controller cont = new Controller();
F>            ...
F>            ITheForm form = mocker.CreateMock<ITheForm>();
F>            Expect.Call(form.ShowDialog(null, null)).IgnoreArguments.Return(DialogResult.OK);
F>            LastCall.IgnoreArguments();
F>            mocker.ReplayAll();

F>            bool res = cont.IsTrue();
F>            Assert.IsFalse(res);
                            mocker.VerifyAll();
F>        }

F>
... << RSDN@Home 1 alpha 4 rev. 0>>
Re[8]: Mock
От: Flea  
Дата: 23.09.08 16:04
Оценка:
Здравствуйте, Time, Вы писали:

T>Всё дело в том что Вы пытаетесь поделать реализацию, вместо интерфейса. здесь. Для Вашего примера надо сделать так (обратите внимание на выделенное жирным):

Сделал через интерфейс, результат тот же.
Код теперь такой:
public interface IForm
    {
        DialogResult ShowDialog(IWin32Window owner, MyType arg);
    }

public partial class TheForm : Form, IForm
    {

        public DialogResult ShowDialog(IWin32Window owner, MyType arg)
        {
        }
    }

        [Test]
        public void IsTrue()
        {
            IForm formMock = m_mocker.CreateMock<IForm>();
            ...
            Expect.Call(formMock.ShowDialog(null, null)).Return(DialogResult.OK);
            LastCall.IgnoreArguments();
            mocker.ReplayAll();
            ...
        }

В документации везде говорится when method is called.. но нигде не нашел instead of..
Мне нужно просто вместо вызова TheForm.ShowDialog(..) вернуть DialogResult.OK и не дать вызваться TheForm.ShowDialog(..).
Такое возможно вообще?
Re[9]: Mock
От: Lloyd Россия  
Дата: 23.09.08 16:55
Оценка:
Здравствуйте, Flea, Вы писали:

F>В документации везде говорится when method is called.. но нигде не нашел instead of..

F>Мне нужно просто вместо вызова TheForm.ShowDialog(..) вернуть DialogResult.OK и не дать вызваться TheForm.ShowDialog(..).
F>Такое возможно вообще?

Зависит от используемого фреймворка. Некоторые поддерживают такое, другие — нет. Смотрите документацию.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[9]: Mock
От: Time Россия  
Дата: 23.09.08 16:59
Оценка:
Здравствуйте, Flea, Вы писали:

F>Мне нужно просто вместо вызова TheForm.ShowDialog(..) вернуть DialogResult.OK и не дать вызваться TheForm.ShowDialog(..).

F>Такое возможно вообще?

Именно для этого и предназначены Mock, обратите внимание ещё раз на мой предыдущий пост.
Особенно,

F> if (Condition)

F> {
F> using (ITheForm form = new TheForm()) <---- именно здесь проблема, Вы создаёте здесь реализацию TheForm, а Вам надо передавать сюда ITheForm, в коде рабочем передавать TheFrom, а в тесте mockTheForm.
F> {
F> form.ShowDialog(null, arg);
F> }
F> }
... << RSDN@Home 1 alpha 4 rev. 0>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.