Просто начинайте с Rhino Mocks и им, имея очень простую проблему, как я издеваюсь над классом с void, который устанавливает свойство?
class SomeClass : ISomeClass
{
private bool _someArg;
public bool SomeProp { get; set; }
public SomeClass(bool someArg)
{
_someArg = someArg;
}
public void SomeMethod()
{
//do some file,wcf, db operation here with _someArg
SomeProp = true/false;
}
}
Очевидно, это очень надуманный пример, спасибо.
В вашем примере вам не понадобятся RhinoMocks, потому что вы, по-видимому, проверяете функциональность тестируемого класса. Вместо этого выполните простое тестирование:
[Test]
public void SomeTest()
{
var sc = new SomeClass();
// Instantiate SomeClass as sc object
sc.SomeMethod();
// Call SomeMethod in the sc object.
Assert.That(sc.SomeProp, Is.True );
// Assert that the property is true...
// or change to Is.False if that what you're after...
}
Гораздо интереснее тестировать mocks, когда у вас есть класс, который имеет зависимости от других классов. В вашем примере вы упомянули:
//Делаем некоторые операции с файлом, wcf, db здесь с _someArg
т.е. вы ожидаете, что какой-либо другой класс установит свойство SomeClass
, что имеет смысл сделать mocktest. Пример:
public class MyClass {
ISomeClass _sc;
public MyClass(ISomeClass sc) {
_sc = sc;
}
public MyMethod() {
sc.SomeProp = true;
}
}
Требуемый тест будет выглядеть примерно так:
[Test]
public void MyMethod_ShouldSetSomeClassPropToTrue()
{
MockRepository mocks = new MockRepository();
ISomeClass someClass = mocks.StrictMock<ISomeClass>();
MyClass classUnderTest = new MyClass(someClass);
someClass.SomeProp = true;
LastCall.IgnoreArguments();
// Expect the property be set with true.
mocks.ReplayAll();
classUndertest.MyMethod();
// Run the method under test.
mocks.VerifyAll();
}
В зависимости от того, насколько вы верны в своем макетном объекте. Легкий способ сделать это - не беспокоиться об этом и выписывать некоторые немые ожидающие утверждения.
[Test]
public void SomeTest()
{
MockRepository mocks = new MockRepository();
ISomeClass mockSomeClass = mocks.StrictMock<ISomeClass>();
using(mocks.Record())
{
using(mocks.Ordered())
{
Expect.Call(MockSomeClass.SomeProp).Return(false);
Expect.Call(delegate{MockSomeClass.SomeMethod();});
Expect.Call(MockSomeClass.SomeProp).Return(true);
}
}
}
Если вы хотите что-то, что больше похоже на реальный объект без консервированного набора упорядоченных ответов, вам нужно будет настроить делегатов с помощью метода do в ожидании.
delegate bool propDelegate();
delegate void methodDelegate();
private bool m_MockPropValue = false;
[Test]
public void SomeTest()
{
MockRepository mocks = new MockRepository();
ISomeClass mockSomeClass = mocks.StrictMock<ISomeClass>();
using(mocks.Record())
{
SetupResult.For(MockSomeClass.SomeProp).Do(new propDelegate(delegate
{
return this.m_MockPropValue;
}));
Expect.Call(delegate{MockSomeClass.SomeMethod();}).Do(new methodDelegate(delegate
{
this.m_MockPropValue = true;
}));
}
}
Неясно, из какого объекта вы пытаетесь проверить, что объект, который вы пытаетесь проверить, - если вы просто хотите проверить, что SomeClass.SomeMethod() устанавливает свойство, вам не нужно насмехаться, так как вы можете просто сделать простой государственный тест:
[TestMethod]
public void SomeMethodTest()
{
SomeClass s = new SomeClass();
s.SomeMethod();
Assert.AreEqual(expectedValue, s.SomeProp);
}
В качестве альтернативы, если SomeClass является зависимостью для какого-либо другого класса, и вы хотите протестировать взаимодействие между этим классом и SomeClass, тогда вы настроите ожидание на вызов метода в разделе "Запись" теста, используя RhinoMock, например:
[TestMethod]
public void CheckInteractionWithSomeClass()
{
MockRepository mocks = new MockRepository();
ISomeClass someClass = mocks.StrictMock<ISomeClass>();
using (mocks.Record())
{
//record expection that someClass.SomeMethod will be called...
someClass.SomeMethod();
}
using (mocks.Playback())
{
//setup class under test - ISomeClass is injected through the constructor here...
ClassUnderTest o = new ClassUnderTest(someClass);
o.MethodOnClassUnderTestThatShouldCallSomeClass.SomeMethod();
//any other assertions...
}
}
Когда вы готовите что-либо с помощью SetupResult.For
или Expect.Call
, вам нужно убедиться, что они виртуальны, иначе RhinoMocks не сможет выполнить свою собственную реализацию.
В противном случае это просто вопрос определения результатов и ожидаемых вызовов как Скотт Педерсен показал