单元测试静态类的静态方法

Geo*_*geB 10 c# unit-testing

public static class ApplicationUtils
{
   public static bool IsCurrentUserAManager()
        {
            var username = WindowsIdentity.GetCurrent().Name;

            bool inAdmin;

            if (username == "AdminUser") {
               inAdmin = true;
            } else {
               inAdmin = false;
            }

            return inAdmin;
        }
  }
Run Code Online (Sandbox Code Playgroud)

以上是一些用于测试当前登录用户是否为管理员的代码,我想通过传入不同的用户名来对本节进行单元测试,并测试结果是否正确。

我听说依赖注入是最好的方法。但我不知道如何依赖注入静态类和静态方法。

任何人都可以帮助我填写下面的 TestMethod 以传递用户名并测试该方法吗?(不使用企业

[TestMethod]
public void IsCurrentUserAManagerTestIsAdmin()
{

}
Run Code Online (Sandbox Code Playgroud)

Dav*_*tin 8

稍微重构你的类以将身份作为参数。

public static class ApplicationUtils
{
    public static bool IsUserAManager(IIdentity identity)
    {
        if (identity == null)
            throw new NullReferenceException("identity");


        return identity.Name == "AdminUser";
    }
}
Run Code Online (Sandbox Code Playgroud)

和你的测试类使用最小起订量

[TestMethod]
public void IsUserAManagerTestIsAdminReturnsFalse()
{
    var mockedIdentity = new Moq.Mock<IIdentity>();
    mockedIdentity.Setup(x => x.Name).Returns("notanadmin");

    var result = ApplicationUtils.IsUserAManager(mockedIdentity.Object);

    Assert.IsFalse(result);
}

[TestMethod]
public void IsUserAManagerTestIsAdminReturnsTrue()
{
    var mockedIdentity = new Moq.Mock<IIdentity>();
    mockedIdentity.Setup(x => x.Name).Returns("AdminUser");

    var result = ApplicationUtils.IsUserAManager(mockedIdentity.Object);

    Assert.IsTrue(result);
}
Run Code Online (Sandbox Code Playgroud)


Nko*_*osi 5

人们应该尽量避免将代码耦合到静态类,因为它们很难测试。

也就是说,按照您当前的代码,可以对其进行重构,以允许某些关注点分离,并通过扩展方法提供更流畅的 API。

public static class ApplicationUtils {
    public static Func<IIdentity> userFactory = () => WindowsIdentity.GetCurrent();

    public static IIdentity CurrentUser { get { return userFactory(); } }

    public static bool IsManager(this IIdentity identity) {
        return identity != null && string.Compare(identity.Name, "AdminUser", true) == 0;
    }

    public static bool IsAuthenticated(this IIdentity identity) {
        return identity != null && identity.IsAuthenticated;
    }
}
Run Code Online (Sandbox Code Playgroud)

下面以测试为例,演示一下上面的使用方法。

Moq 被用作模拟框架

[TestMethod]
public void IsManager_Should_Return_True_For_AdminUser() {
    //Arrange
    var name = "AdminUser";
    var identity = Mock.Of<IIdentity>(_ => _.Name == name);
    ApplicationUtils.userFactory = () => identity;

    //Act
    var actual = ApplicationUtils.CurrentUser.IsManager();

    //Assert
    Assert.IsTrue(actual);
}
Run Code Online (Sandbox Code Playgroud)

完成后,我现在建议您重构代码以使其更加可靠。

将当前用户转移到服务提供商的功能进行抽象。

public interface IIdentityProvider {
    IIdentity CurrentUser { get; }
}
Run Code Online (Sandbox Code Playgroud)

非常简单,实现更简单。

public class DefaultIdentityProvider : IIdentityProvider {
    public IIdentity CurrentUser {
        get { return WindowsIdentity.GetCurrent(); }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果使用 DI,您现在可以将提供程序注入到需要访问当前用户的依赖类中。

这使得代码更加灵活和可维护,因为提供者和用户的模拟/存根可用于隔离的单元测试。扩展方法保持不变,因为它们的关注点非常简单。

下面是对之前的扩展方法进行测试的简单示例。

[TestMethod]
public void IsManager_Should_Return_True_For_AdminUser() {
    //Arrange
    var name = "AdminUser";
    var identity = Mock.Of<IIdentity>(_ => _.Name == name);
    var provider = Mock.Of<IIdentityProvider>(_ => _.CurrentUser == identity);

    //Act
    var actual = provider.CurrentUser.IsManager();

    //Assert
    Assert.IsTrue(actual);
}
Run Code Online (Sandbox Code Playgroud)

纯粹出于演示目的,扩展方法的测试IsManager实际上只需要IIdentity进行。

Assert.IsTrue(Mock.Of<IIdentity>(_ => _.Name == "AdminUser").IsManager());
Run Code Online (Sandbox Code Playgroud)

  • @DavidMartin,他知道是什么激励了这个优秀机构的一些成员。 (5认同)