NUnit - 静态比。公共方法

时间:2013-07-23 16:36:51

标签: c# .net unit-testing nunit

我的项目在规模和功能方面都在不断增长,所以我决定使用NUnit测试一些功能但是我面临的问题是大多数方法都是静态的,所以首先要发现的是创建公共方法我从Unit Test类调用它们但是那些公共方法开始很多,所以我想知道如果不是在主类中创建新的Public方法,我应该创建一个接口或者如果静态方法应该是Public并且是使用类中间实例化。

这是我的程序结构的一个例子,

namespace Mynamespace
{
    public class Foo
    {
         InsertUser();
         SortUser();
    }

    static void InsertUser()
    {

    }

    static void SortUser()
    {

    }

    //Here start the public methods to be called from the unit test class

    public DoSort() 
    {
        InsertUser();
        SortUser();
    }
}

将程序的主要逻辑和测试类分开的最佳方法是什么?

谢谢,

2 个答案:

答案 0 :(得分:1)

不是保留静态方法和添加非静态方法,最好将所有方法从静态转换为实例方法,并提取Foo类客户端依赖的抽象:

public interface IFoo
{
     void InsertUser();
     void SortUser();
}

public class Foo : IFoo
{
     void InsertUser() { ... }
     void SortUser() { ... }
}

静态成员将耦合引入您的应用程序。模拟静态成员真的很头疼。您应该program to abstraction, instead of programing to implementation以使您的代码可以测试并loosely coupled。当您的代码依赖于接口而不是静态类时,您可以轻松地mock这种依赖:

Mock<IFoo> fooMock = new Mock<IFoo>();
fooMock.Setup(f => f.InsertUser()).Throws<InvalidOperationException>();

var sut = new ClassUnderTest(fooMock.Object);
fooMock.VerifyAll();

如果你真的需要在全局范围内访问这些方法(这不是一个好主意 - 它是一种程序化的编程风格),那么将你的类实现为Singleton

public class Foo : IFoo
{
     public static Foo Instance = new Foo(); // simple singleton implementation
     private Foo() { }

     void InsertUser() { ... }
     void SortUser() { ... }
}

您可以在应用程序的任何位置获取类实例

IFoo foo = Foo.Instance;
foo.SortUser();

答案 1 :(得分:1)

在我看来,你应该让你的真正的类和你的单元类都实现一个通用的接口,如下所示:

interface IFoo
{
    void InsertUser();
    void SortUser();
}

对于您的实际实施,请使用:

public class RealFoo : IFoo
{
    public void InsertUser()
    {
        throw new NotImplementedException();
    }

    public void SortUser()
    {
        throw new NotImplementedException();
    }
}

对于您的测试类,请使用:

public class FakeFoo : IFoo
{
    public void InsertUser()
    {
        throw new NotImplementedException();
    }

    public void SortUser()
    {
        throw new NotImplementedException();
    }
}

注意:您的FakeFoo类不需要与RealFoo类位于同一位置,而是您的IFoo接口定义应该被每个项目引用(一个用于实际实现,另一个用于测试项目。)

如果你的IFoo界面变得太大(阅读:方法太多),那么你可以使用Repository Pattern,它会将你的方法划分为更接近功能性的接口。