给定一个预期会抛出异常的构造函数:
public class MyObject
{
public MyObject(String name)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
this.Initialize();
}
protected virtual void Initialize()
{
// do stuff
}
}
我如何使用Machine.Fakes与Rhino(默认情况下,我正在转向Rhino)来模拟这个类,并测试:
使用Moq,我可以模拟实际的MyObject类本身,并在模拟Callbase = true
上设置属性,使其像普通类一样运行。
然后,我可以验证是否抛出了异常,并且未使用此方法调用该方法:
// all pseudo code to prove my point of "creating an instance"
//
void when_creating_new_MyObject_with_null_Name_should_throw_Exception()
{
// arrange
Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty);
myObjectToTest.Callbase = true;
// act
Assert.Throws<ArgumentNullException>(() =>
var instance = myObjectToTest.Object;
);
}
void when_creating_new_MyObject_with_null_Name_should_not_call_Initialize()
{
// arrange
Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty);
myObjectToTest.Callbase = true;
// act
try
{
// creates an instance
var instance = myObjectToTest.Object;
}
catch {}
// assert
myObjectToTest.Verify(x => x.Initialize(), Times.Never());
}
但是我无法弄清楚如何使用MSpec w / Fakes来模拟它:
[Subject(typeof(MyObject), "when instantiating a new instance")
class with_null_Name
{
static MyObject myObjectToTest;
static Exception expectedException;
Establish context =()=>
myObjectToTest = An<MyObject>(String.Empty);
Because of; // I don't think there is anything to act on here?
It should_throw_Exception;
// how to capture exception with An<T>()?
It should_not_call_Initialize = () =>
myObjectToTest.WasNotToldTo(x => x.Initialize());
}
我确实知道Catch.Exception(...)
行为中的Because of
通常情况。但是这个用例似乎并不适用。
任何指针都会受到赞赏。
谢谢!
免责声明:真实世界的用例相当复杂,重要的对象要启动,这对于缓存的后备成员而言非常昂贵。上面的代码只是一个简化版本。
答案 0 :(得分:3)
对我来说没有意义测试一个模拟的sut
,模拟行为是由你在测试方法中定义的。你应该测试真实物体
在这种情况下,您应该只验证在提供错误数据时抛出异常
我想你知道该怎么做但无论如何这里是代码:
[Subject(typeof (MyObject), "when instantiating a new instance")]
internal class with_null_Name
{
static MyObject myObjectToTest;
static Exception expectedException;
Because of = () => expectedException = Catch.Exception(
() => myObjectToTest = new MyObject(String.Empty));
It should_fail = () => expectedException.ShouldNotBeNull();
}
答案 1 :(得分:2)
就个人而言,我不习惯使用模拟框架来模拟被测单元中的。我使用模拟来使用依赖注入来破坏外部依赖项。我绝不是这方面的专家,但我的直觉是,这个细节太精细了。
你说你的真实世界情况有很多要初始化的对象;难道你不能模拟这些对象中的一个或多个并检查它们是否被调用?或者,使用依赖注入来注入一些可以设置标志的伪对象。
这些建议对我来说都显得很臭。最后,您知道是否抛出了未调用Initialize的异常。我想我明白你正在努力确保一个错误不会在未来的编辑中蔓延,但你实际上是在对这里的开发人员进行单元测试吗?我个人认为在提供错误数据时验证是否会抛出异常就足够了。我很想听到任何不同的意见。