Я новичок в Rhino Mocks, так что я могу что-то упустить полностью.
Допустим, у меня есть интерфейс с полдюжины свойств:
public interface IFoo {
string Foo1 { get; } // Required non-null or empty
string Foo2 { get; } // Required non-null or empty
string Foo3 { get; }
string Foo4 { get; }
int Foo5 { get; }
int Foo6 { get; }
}
И реализация, которая принимает похожий объект, но без тех же ограничений и создает экземпляр IFoo:
public interface IFooLikeObject {
string FooLikeObject1 { get; } // Okay non-null or empty
string FooLikeObject2 { get; } // Okay non-null or empty
string FooLikeObject3 { get; }
string FooLikeObject4 { get; }
string FooLikeObject5 { get; } // String here instead of int
string FooLikeObject6 { get; } // String here instead of int
}
public class Foo : IFoo {
public Foo(IFooLikeObject fooLikeObject) {
if (string.IsNullOrEmpty(fooLikeObject.Foo1)) {
throw new ArgumentException("fooLikeObject.Foo1 is a required element and must not be null.")
}
if (string.IsNullOrEmpty(Foo2)) {
throw new ArgumentException("fooLikeObject.Foo2 is a required element and must not be null")
}
// Make all the assignments, including conversions from string to int...
}
}
Теперь в моих тестах я хочу проверить, что исключения генерируются в нужное время, а также исключения, возникающие при неудачном преобразовании строки в int.
Так что мне нужно слишком заглушить IFooLikeObject, чтобы возвращать действительные значения для значений, которые я в данный момент не тестирую, и, поскольку я не хочу дублировать этот код в каждом методе тестирования, я извлекаю его в отдельный метод.
public IFooLikeObject CreateBasicIFooLikeObjectStub(MockRepository mocks) {
IFooLikeObject stub = mocks.Stub<IFooLikeObject>();
// These values are required to be non-null
SetupResult.For(stub.FooLikeObject1).Return("AValidString");
SetupResult.For(stub.FooLikeObject2).Return("AValidString2");
SetupResult.For(stub.FooLikeObject5).Return("1");
SetupResult.For(stub.FooLikeObject6).Return("1");
}
Этого достаточно для тестирования Foo3 и Foo4, но при тестировании Foo1, 2, 5 или 6 я получаю:
System.InvalidOperationException : The result for IFooLikeObject.get_FooLikeObject1(); has already been setup. Properties are already stubbed with PropertyBehavior by default, no action is required
Например:
[Test]
void Constructor_FooLikeObject1IsNull_Exception() {
MocksRepository mocks = new MocksRepository();
IFooLikeObject fooLikeObjectStub = CreateBasicIFooLikeObjectStub(mocks);
// This line causes the exception since FooLikeObject1 has already been set in CreateBasicIFooLikeObjectStub()
SetupResult.For(fooLikeObjectStub.FooLikeObject1).Return(null);
mocks.ReplayAll();
Assert.Throws<ArgumentException>(delegate { new Foo(fooLikeObjectStub); });
}
Как я могу настроить его так, чтобы я мог переопределить отдельное свойство, для которого уже установлено возвращаемое значение, без необходимости повторного выполнения всех остальных?