我知道这是一个普通的编程问题,但我在过去几次搜索过它,但我从来没有找到一个坚定的答案。
几个月前,我和另一家公司的一位高级工程师进行了一次关于接口的谈话。他说,他更喜欢为所有事物编写接口,因为它允许他“测试接口”。我当时没有想太多这个短语(如果我想过的话,我就会要求他解释!)但这让我有点困惑。
我认为这意味着他将编写一个基于接口的单元测试,然后该测试将用于分析接口的每个实现。如果这是他的意思,那对我来说是有道理的。但是,这种解释仍然让我想知道,当您的一个实现公开了接口中没有定义的其他公共方法时,最佳实践是什么?你能为那堂课再写一次考试吗?
预先感谢你对这个问题的任何想法。
发布于 2014-01-17 16:34:37
对接口的测试--虽然我以前从未听说过这个术语--基本上意味着,当您测试接口的具体实现时,您只测试该接口提供的方法。例如,考虑以下类:
interface A
{
int MustReturn3();
}
class B : A
{
public int MustReturn3()
{
return Get3();
}
public int Get3()
{
return 2 + 1;
}
}当您想测试implementation of A时,您要测试什么?我的实现是B。我想确保B完成了A应该完成的任务。
我并不真正关心测试Get3()。我只关心MustReturn3()将遵循接口细节,即它将返回3。
所以我会写一个这样的测试:
private A _a;
[TestInitialize]
public void Initialize()
{
_a = new B();
}
[TestMethod]
public void ShouldReturn3WhenICallMustReturn3()
{
Assert.AreEqual(3, _a.MustReturn3());
}这确保了我没有测试任何实现细节;我只是测试接口告诉我类实现应该做什么。
实际上,这就是我写单元测试的方式。您可以看到像这个这里这样的测试的真正工作版本。
发布于 2014-01-17 16:20:25
你确定他说的是对接口的测试而不是程序到接口
简单地说,对接口的程序意味着类不应该依赖于具体的实现。相反,它们应该依赖于接口。
它的优点是您可以为接口提供不同的实现,这使您能够对类进行单元测试,因为您可以为该接口提供一个模拟/存根。
想象一下这个例子:
public class SomeClass{
StringAnalyzer stringAnalizer = new StringAnalizer();
Logger logger = new Logger();
public void SomeMethod(){
if (stringAnalyzer.IsValid(someParameter))
{
//do something with someParameter
}else
{
logger.Log("Invalid string");
}
}
}与此形成对比:
class SomeClass
{
IStringAnalyzer stringAnalizer;
ILogger logger;
public SomeClass(IStringAnalyzer stringAnalyzer, ILogger logger)
{
this.logger = logger;
this.stringAnalyzer = stringAnalyzer;
}
public void SomeMethod(string someParameter)
{
if (stringAnalyzer.IsValid(someParameter))
{
//do something with someParameter
}else
{
logger.Log("Invalid string");
}
}
}这使您能够编写这样的测试:
[Test]
public void SomeMethod_InvalidParameter_CallsLogger
{
Rhino.Mocks.MockRepository mockRepository = new Rhino.Mocks.MockRepository();
IStringAnalyzer s = mockRepository.Stub<IStringRepository>();
s.Stub(s => s.IsValid("something, doesnt matter").IgnoreParameters().Return(false);
ILogger l = mockRepository.DynamicMock<ILogger>();
SomeClass someClass = new SomeClass(s, l);
mockRepository.ReplayAll();
someClass.SomeMethod("What you put here doesnt really matter because the stub will always return false");
l.AssertWasCalled(l => l.Log("Invalid string"));
}因为在第二个示例中,您依赖于接口而不是具体的类,所以您可以很容易地在测试中通过伪交换它们。这只是优势之一,归根结底,这种方法使您能够利用多态,这不仅对测试有用,而且对于您可能希望为类的依赖项提供替代实现的任何情况都是有用的。
以上示例的完整解释可以找到这里。
发布于 2014-01-17 16:17:47
它使单元测试更容易,因为您可以轻松地模拟接口,以返回测试代码所需的数据。
https://stackoverflow.com/questions/21190518
复制相似问题