【问题标题】:How to rewrite code to avoid call to external dll during unit test如何重写代码以避免在单元测试期间调用外部dll
【发布时间】:2016-02-19 13:56:51
【问题描述】:

有类Driver,在构造函数中调用静态extern方法。这是更改架构以便能够对 Driver 方法进行单元测试的最佳方法。

public class Driver
{
    [DllImport("Driver.dll")]
    private static extern IntPtr CreateDriver();

    // Pointer to C++ Driver object
    internal IntPtr DriverPtr; // this for integration tests

    public Driver()
    {
        DriverPtr = CreateDriver();
    }

    public int SomeMethod(int a) // test only this method
    {
        return a + 1;
    }
}

【问题讨论】:

  • 您如何处理Driver 类中的DriverPtr?在您的示例中,除了创建它之外,您什么都不做。
  • 其实没关系。这个想法是使用单元测试来测试 SomeMethod() 。单元测试不能调用dll。

标签: c# unit-testing architecture dllimport extern


【解决方案1】:

您的故事并不完全清楚,但我认为您是在问如何在无需与实际驱动程序 DLL 交互的情况下测试代码。目前尚不清楚您是否要在构造函数中使用分配给DriverPtr 的值。

您可以通过将静态方法移动到实例类中来解决此问题,连接该类并在测试期间模拟它。

界面:

public interface IDriverProvider
{
    IntPtr Create();
}

实施:

public class DriverProvider : IDriverProvider
{
    [DllImport("Driver.dll")]
    private static extern IntPtr CreateDriver();

    public IntPtr Create()
    {
        return CreateDriver();
    }
}

然后将其注入到您的使用类中:

public class Driver
{
    internal IntPtr DriverPtr;

    public Driver(IDriverProvider driverProvider)
    {
        DriverPtr = driverProvider.Create();
    }

    public int SomeMethod(int a) // test this method
    {
        return a + 1;
    }
}

现在你可以测试你的类了:

// Arrange
var driverProviderMock = new Mock<IDriverProvider>();   
var driver = new Driver(driverProviderMock.Object);

// Act
driver.SomeMethod();

// Assert
driverProviderMock.Verify(d => d.Create());

【讨论】:

  • 我刚刚编写了相同的代码,我也将其称为 IDriveProvider。该死的。 :)
  • @Malmi 命名很难,但我不想花太多时间在上面。 :P
  • 我的回答被否决是因为它不正确,还是因为有人不会管理他们错了?
  • 这正是解决方案。谢谢!
  • @CodeCaster 抱歉,删除了我的评论。我心目中的人错了。 :P 你的解决方案很棒。
【解决方案2】:

有很多方法,这取决于你想做什么。

例如,您可以创建一个带有额外参数的虚拟构造函数,而不进行调用:

public Driver(bool dummy){ }

或者把构造函数改成做注释,然后有一个Init()函数:

public Driver(){ } //Can be removed, left for example clarity

public void Init(){ DriverPtr = CreateDriver(); }

【讨论】:

  • "可以创建一个带有额外参数的虚拟构造函数" - 只是为了能够对其进行单元测试?不。 “然后有一个 Init() 函数” - 然后呢?
  • 类不用于测试时调用Init。
  • 我不是 OP,但他们显然想在某个地方访问 DriverPtr
  • 如果他想使用它,那么无论如何都必须调用DLL,所以这个问题没有意义,看看他发布的函数示例,没有引用指针。
  • 如果你可以使用继承的类,那么init方法就不需要了,让你的类保持原样,只用一个空的构造函数创建一个新类,这样原来的构造函数就不会被执行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-25
  • 1970-01-01
相关资源
最近更新 更多