给出如下界面:
public interface IFoo
{
string Bar();
}
和一个实现它的类,如:
public class Foo : IFoo
{
public string Bar()
{
returns "Bar";
}
public string SomeOtherMethod()
{
returns "Something else";
}
}
此代码是否有问题?是否应该将所有成员添加到界面?
一个例子:想象一个私有方法,它变得足够复杂以至于需要进行单元测试。您可以将其公开(以便可以从测试项目中调用它),但是不能将其添加到接口中(因为没有客户端需要调用它)?
答案 0 :(得分:2)
通常,当一个类实现一个接口时,必须实现该接口的所有成员,否则就不会相反。
此外,在实现接口成员时,实现类的相应成员也必须是公共的,非静态的,并且具有与接口成员相同的名称和参数签名。在接口中未定义的类中,甚至可以包含公共方法。
最重要的是,接口本身不提供类或结构可以继承基类功能的方式继承的功能。但是,如果基类实现了接口,则从基类派生的任何类都将继承该实现。
答案 1 :(得分:1)
如果一个类所做的事情很简单,我们可以同时测试其公共方法和私有方法,那么我们就可以测试公共方法。
如果私有方法变得如此复杂,以至于在公共方法和私有方法之间我们需要太多的测试组合,那么该将私有方法分为自己的类了。将私有方法公开将破坏该类的封装。即使我们不将方法添加到interface
中,将类方法设置为公共方法仍会将方法添加到类本身的公共接口 。
所以,如果我们有这个:
public class ClassWithComplexPrivateMethod
{
public void DoSomething(int value)
{
PrivateMethodThatNeedsItsOwnTests(value);
}
private string PrivateMethodThatNeedsItsOwnTests(int value)
{
// This method has gotten really complicated!
return value.ToString();
}
}
我们可能会重构为以下内容:
public interface IRepresentsWhatThePrivateMethodDid
{
string MethodThatNeedsItsOwnTests(int value);
}
public class RefactoredClass
{
private readonly IRepresentsWhatThePrivateMethodDid _dependency;
public RefactoredClass(IRepresentsWhatThePrivateMethodDid dependency)
{
_dependency = dependency;
}
public string DoSomething(int value)
{
return _dependency.MethodThatNeedsItsOwnTests(value);
}
}
现在,一个新类实现了IRepresentsWhatThePrivateMethodDid
。
现在,当我们测试重构的类时,我们会模拟IRepresentsWhatThePrivateMethodDid
,并为实现IRepresentsWhatThePrivateMethodDid
的任何类编写单独的单元测试。
说将私有方法公开为公开会破坏封装似乎是矛盾的,但将其公开为自己的单独类却没有。有两个区别:
当我们可以通过公共方法测试该类(包括其私有方法)时,也很容易对此感到厌烦并过早引入单独的依赖关系。我已经做了很多次,它会导致很多不必要的接口和额外的类。没有完美,只有我们尽最大的努力来平衡它。
再想一想:我们倾向于使用接口来表示依赖关系,但是我们不必这样做。如果我们提取的只是一个私有方法,那么也许可以用委托或Func
来表示它,就像这样:
public class RefactoredClass
{
private readonly Func<int, string> _dependency;
public RefactoredClass(Func<int, string> dependency)
{
_dependency = dependency;
}
public string DoSomething(int value)
{
return _dependency(value);
}
}
或者我们可以使用一个委托,我比Func
更喜欢,因为它表明了函数的作用。
答案 2 :(得分:0)
接口应仅代表所需的API,而无需考虑单元测试和其他问题。
要测试类的 public 方法,您应该不执行 ,因为Test-project可以访问它们。您只需要实例化一个类并使用Mock注入所有必需的依赖项。
Example: testing class without any dependencies
Example: testing class with dependency
要测试类的私有方法,需要使它们对测试项目可见: