如何重写代码以避免在单元测试期间调用外部dll

时间:2016-02-19 13:56:52

标签: c# unit-testing architecture dllimport extern

有类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;
    }
}

2 个答案:

答案 0 :(得分:3)

您的故事并不完全清楚,但我认为您在不必与实际驱动程序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());

答案 1 :(得分:0)

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

每个例子,您可以使用额外的参数创建一个虚拟构造函数,但不要进行调用:

public Driver(bool dummy){ }

或者更改构造函数以进行注释,然后使用Init()函数:

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

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