【问题标题】:Accessing internal methods through a public interface [duplicate]通过公共接口访问内部方法[重复]
【发布时间】:2018-03-07 19:05:40
【问题描述】:

情况

假设我有一个带有内部方法的类:

class MyClass : IMyClass
{
    public void PublicMethod() { ... }
    internal void InternalMethod() { ... }
}

实现一个接口:

interface IMyClass
{
    void PublicMethod() { ... }
}

还有一个容器类,其中包含MyClass 和其他具体类的实例:

class ContainerClass
{
    public MyClass myClass;
    ...
}

ContainerClass 被各种程序集使用。在与MyClass 相同的程序集中使用时,调用方法可以调用containerClass.myClass.InternalMethod()


问题

为了使测试更容易模拟,我现在尝试用接口而不是具体类替换ContainerClass 的属性,例如:

class ContainerClass
{
    public IMyClass myClass;
    ...
}

但是, 如果我这样做,InternalMethod 将无法再使用 containerClass.myClass.InternalMethod() 调用,因为该方法在接口上不存在...也 不能 它,因为它是internal。但是,我无法将接口设为内部,因为 ContainerClass 也被其他程序集使用。

假设我无法更改internal 对该方法的访问权限。还有其他方法吗?


编辑: 这与How to Mock the Internal Method of a class? 不同,因为我不是在尝试模拟内部方法,而是在用接口替换具体类(MyClass)时尝试使其暴露(IMyClass)。

【问题讨论】:

  • @elgonzo 我的目标不是模拟内部方法(我的测试不需要模拟它)。这个问题是由接口IMyClass替换具体类MyClass引起的:内部方法变得不可见/不可访问,因为它没有通过接口公开。
  • 等等...所以您想模拟 MyClass 的部分而不模拟 MyClass 的其他部分?有些东西似乎没有加起来,或者我完全误解了你......
  • @elgonzo 我可能只是没有很好地解释自己。问题本身与嘲笑无关。这个问题是在试图让事情更容易模拟时出现的(即通过使用带有接口的 DI 而不是将ContainerClass 紧密耦合到MyClass),因为其他(遗留)代码调用MyClass 上的内部方法through ContainerClass 的一个实例。
  • 啊,好的。现在得到你了。使用一些抽象基类而不是接口是否可行?基类可以提供(虚拟)内部方法。然后,您将拥有两个基于此抽象基类的不同实现;一个普通的“生产类”和另一个用于测试的实现(有或没有公共和/或内部方法的单独覆盖)
  • 嗯,你可能正在那里做些什么。我现在正在尝试另一种可能的解决方案,但如果这不起作用,我会试试你的。

标签: c# interface


【解决方案1】:

一种选择是创建两个接口,一个是公共的,一个是内部的:

public interface IMyClassPublic
{
    void PublicMethod();
}

internal interface IMyClassInternal
{
    void InternalMethod();
}

MyClass 中实现它们(您需要明确实现IMyClassInternal,因为它是内部的):

public class MyClass : IMyClassPublic, IMyClassInternal
{
    public void PublicMethod() {  }
    void IMyClassInternal.InternalMethod() {  }
}

并更改ContainerClass,使其分别公开两个接口(并可能将myClass设为私有):

public class ContainerClass
{
    private MyClass myClass;
    public IMyClassPublic myClassPublic
    {
        get
        {
            return myClass;
        }
    }

    internal IMyClassInternal myClassInternal
    {
        get
        {
            return myClass;
        }
    }
}

现在你可以同时模拟它们了,使用内部方法containerClass.myClassInternal.InternalMethod()和公共方法containerClass.myClassPublic.PublicMethod()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-27
    • 2016-06-06
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 2013-09-11
    • 2014-06-21
    • 2021-06-14
    相关资源
    最近更新 更多