如何重置存根中属性的结果而不重置整个存根?
我是 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...
}
}
现在在我的测试中,我想测试在适当的时间抛出异常以及从 string 到 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); });
}
我如何设置它,以便我可以覆盖已经设置了返回值的单个属性,而无需还必须重做所有其他的吗?
I'm new to Rhino Mocks, so I may be missing something completely.
Lets say I have an interface with has a half dozen properties:
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; }
}
And an implementation which takes a similar object but without the same constraints and creates an IFoo instance:
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...
}
}
Now in my tests I want to test both that the exceptions are thrown at the proper times and also the exceptions thrown during failed conversions from string to int.
So I need too stub out IFooLikeObject to return valid values for the values I'm not currently testing, and since I don't want to duplicate this code in every test method I extract it out into a seperate method.
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");
}
This works well enough for testing Foo3 and Foo4, but when testing Foo1, 2, 5, or 6 I get:
System.InvalidOperationException : The result for IFooLikeObject.get_FooLikeObject1(); has already been setup. Properties are already stubbed with PropertyBehavior by default, no action is required
For example:
[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); });
}
How can I set it up so that I can override an individual property which already has a return value set up without having to redo all the others as well?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可以使用
Repeat.Any()
构造来完成。我尚未使用 SetupResult.For 语法对此进行测试,但它适用于 lambda 语法:
我发现的唯一警告是您不能执行两次。
This can be done using the
Repeat.Any()
construct.I have not tested this using the SetupResult.For Syntax, but it works with the lambda syntax:
The only caveat I've found is you can't do it twice.
我可能错过了一些东西,但是你尝试过这样做吗?
使用存根,您可以直接将属性设置为您想要的内容。
如果该属性是只读的,您可以这样做:
I might be missing something, but have you tried just doing this?
With stubs, you can just set the properties to what you want them to be directly.
If the property is read only you could do it like this: