我对Rhino Mocks有点问题。
我有一个抽象类,其中一个方法需要一个对象(在一个字符串下面的示例中)。该方法检查参数是否为空。
public abstract class Foo
{
public void DoSomething(string bar)
{
if (bar == null)
{
throw new ArgumentNullException("bar");
}
}
}
我有另一个类,它使用Foo
:
public class Baz
{
private readonly Foo foo;
public Baz(Foo foo)
{
this.foo = foo;
}
public void DoWork(string s)
{
s = "xxx" + s;
this.foo.DoSomething(s);
}
}
我想进行单元测试并检查是否使用正确的参数调用类DoSomething
的{{1}}。我使用了Foo
。
Arg<T>.Matches()
现在,当我尝试运行此测试时,会在 [Test]
public void TestMethod()
{
var fooMock = MockRepository.GenerateMock<Foo>();
var objectUnderTest = new Baz(fooMock);
fooMock.Expect(x => x.DoSomething(Arg<string>.Matches(Text.StartsWith("xxx"))))
.Repeat.Once();
objectUnderTest.DoWork("hello");
fooMock.VerifyAllExpectations();
}
处引发ArgumentNullException
。我查看了Rhino Mocks的代码,发现Expect(...)
- 方法始终返回Match()
,对于字符串(以及其他所有类),它都是default(T)
。因此,null
签入会引发DoSomething()
。
我知道,我可以为ArgumentNullException
提取接口并创建该接口的模拟,因此没有空检查。但我想知道这个问题是否可以通过保留代码来解决Rhino Mocks(当然除了单元测试;-))。
答案 0 :(得分:-1)
仅通过更改测试代码无法解决问题。被测代码是以非测试友好的方式编写的。
原因是Rhino Mock需要模拟/存根方法才能被覆盖。即DoSomething()
应为界面方法(如您所述)或虚拟方法。
如果它是可覆盖的,则根本不会在DoSomething()
调用中触发真实方法Expect()
。
这两个选项都可以工作,但都需要测试更改的代码。
如果可以修改测试中的代码,那么在我看来,IFoo
而不是抽象类Foo
的使用界面是可取的方式。这就是dependency injection应该正确实施的方式。