Я работал над оболочкой для COM-объекта, которая может принимать и возвращать только строки. Интерфейс COM-объекта выглядит так:
interface IMapinfo
{
void Do(string cmd);
string Eval(string cmd);
}
Теперь я создал классы, которые завершают основные функции следующим образом:
public class Table
{
IMapinfo MI;
public string Name
{
//pass the command to the COM object and get back the name.
get{return MI.Eval("TableInfo(1,1")");}
}
}
Теперь я хотел бы провести модульное тестирование этих классов без необходимости каждый раз создавать настоящий COM-объект, настраивать мир, а затем запускать тесты. Итак, я изучал использование имитационных объектов, но я немного смущен тем, как я бы использовал имитацию в этой ситуации.
Я планирую использовать Moq, поэтому я написал этот тест следующим образом:
[Test]
public void MockMapinfo()
{
Moq.Mock<Table> MockTable = new Moq.Mock<Table>();
MockTable.ExpectGet(n => n.Name)
.Returns("Water_Mains");
Table table = MockTable.Object;
var tablename = table.Name;
Assert.AreEqual("Water_Mains", tablename,string.Format("tablename is {0}",tablename));
Table d = new Table();
}
Это правильный способ издеваться над моим COM-объектом? Как это утверждение верно, что строка, отправляемая в функцию eval, верна? или я все не так делаю?





Это дубликат? Как мне сделать TDD с объектом COM OLE
Обновлено: Похоже, вы задаете тот же вопрос, но для проверки своего издевательского кода (OOPS).
Вы не совсем подходите для своего сценария насмешек. Вы правы, что хотите изолировать внешние зависимости, и ваш COM-объект определенно соответствует этим критериям. Хотя я не любитель moq (я предпочитаю RhinoMocks), за mocks стоит идея тестирование взаимодействия ...
Тестирование взаимодействия - это изучение того, как сплоченные наборы объектов работают вместе. Допустимым тестом в этом сценарии было бы написание теста для компонента, который зависит от поведения вашего COM-объекта.
В этом случае ваша «Таблица», которая действует как оболочка для вашего COM-объекта, также зависит от поведения COM-объекта. В качестве аргумента предположим, что ваш объект Table выполняет настраиваемую логику в отношении значений, возвращаемых вашим COM-объектом.
Теперь вы можете писать изолированные тесты для своего объекта Table, в то время как моделирование поведения вашего COM-объекта с помощью Mocks.
public class Table
{
public Table(IMapInfo map)
{
_map = map;
}
public string Name
{
get
{
string value = _map.Eval("myexpression");
if (String.IsNullOrEmpty(value))
{
value = "none";
}
return value;
}
}
private IMapInfo _map;
}
[TestFixture]
public class TableFixture // is this a pun?
{
[Test]
public void CanHandleNullsFromCOM()
{
MockRepository mocks = new MockRepository(); // rhino mocks, btw
IMapInfo map = mocks.CreateMock<IMapInfo>();
using (mocks.Record())
{
Expect.Call(map.Eval("myexpression").Return(null);
}
using (mocks.PlayBack())
{
Table table = new Table(map);
Assert.AreEqual("none", table.Name, "We didn't handle nulls correctly.");
}
mocks.verify();
}
}
Возможно, ваш COM-объект выдает исключения при вызове, а может быть, он не очень хорошо обрабатывает строковые выражения. На самом деле мы тестируем, как наш объект Table взаимодействует с IMapInfo без привязки к реализации COM-объекта. Мы также обеспечиваем связь между Table и IMapInfo в том смысле, что объект IMapInfo должен вызываться во время теста.
Надеюсь это поможет.
и на этот раз я больше ищу вопрос типа "это правильно", а не "если я должен использовать макеты"
Я обновил свой ответ. Ваш пример неверен; вы утверждаете, что фиктивный фреймворк дает вам значение, которое вы ему предоставили, и оно всегда будет проходить. В моем примере показано, как проверить взаимодействие между таблицей и IMapInfo.
Ваш пример был бы правильным, если бы вы тестировали объект, который взаимодействовал с Table. Но просто создать макет, а затем утверждать, что он имеет заданные вами значения, - это не валидный тест.
Мягкость есть, но в то время я просто использовал прямой COM-объект для передачи строк, и теперь у меня есть куча слоев, через которые проходит строка, если это имеет смысл.