gpt4 book ai didi

c# - 如何正确测试这个? (C#、NUnit、最小起订量)

转载 作者:行者123 更新时间:2023-12-02 01:05:47 28 4
gpt4 key购买 nike

我希望这不是太含糊,但我只是在学习使用 NUnit 和 Moq 进行单元测试。我理解这些概念,并且我可以毫不费力地为执行简单任务的逻辑方法编写测试,例如操纵某些值或调用伪造的服务。但我有点摸不着头脑,想弄清楚如何测试如下所示的方法,这是一种需要进行数据调用并具有多个依赖项的方法。

这是我必须根据数据库对用户进行身份验证的类:

class Authenticator: IAuthenticator
{

private IConnectionHelper _connHelper;

public Authenticator(IConnectionHelper connHelper)
{
_connHelper = connHelper;
}

public string UserId { get; set; }
public string Password { get; set; }
public UserModel User { get; private set; }

public bool ValidateUser()
{

if (string.IsNullOrEmpty(UserId))
return false;

if (string.IsNullOrEmpty(Password))
return false;

using (Entities db = new Entities(_connHelper))
{
MD5 md5 = MD5.Create();
byte[] inputBytes = Encoding.ASCII.GetBytes(this.Password);
byte[] hash = md5.ComputeHash(inputBytes);
string md5Hash = BitConverter.ToString(hash).ToUpper().Replace("-", string.Empty);

var query = from u in db.Users
where u.UserId.ToUpper().Trim() == this.UserId.ToUpper()
where u.CPassword.Trim() == md5Hash
select u;

this.User = query.FirstOrDefault();
}



if (this.User == null)
{
Log.LogLine(TraceLevel.Verbose, string.Format("Authentication failed for user '{0}'", this.UserId));
return false;
}
else
{
Log.LogLine(TraceLevel.Verbose, string.Format("Successfully authenticated user '{0}'", this.UserId));
return true;
}
}


}

我想为此创建一个测试夹具,但我不确定如何处理它。

我可以模拟 IConnectionHelper,并测试如果 UserId 或密码为 null/空,该方法将失败,但这是我所能得到的。如果 IConnectionHelper 是假的,那么我显然将无法测试数据库内容,我不确定我是否应该这样做。有人可以阐明这里的最佳做法吗?

编辑

StuartLc 接受的答案无疑让我朝着正确的方向前进。我确实需要为 Entity Framework 做一些额外的设置工作,基本上使用它作为引用:http://msdn.microsoft.com/en-us/data/dn314429.aspx

最佳答案

根据 Ryan 的评论,您的代码与依赖项 EntitiesLog 的耦合过于紧密,以至于无法轻松进行单元测试(无需求助于 Moles 假货)。

作为一般规则,使用 new 来创建任何实质性依赖,或使用 static 方法(如 Log)通常是阻止的罪魁祸首使用 Moq 等框架进行独立单元测试。

我建议重构代码如下:

  1. 将创建 Entities 类(大概是一个 ORM 工件,如 EF DbSet 或 Linq DataContext)的关注点分离到一个工厂,通过接口(interface)。
  2. 可以将 IConnectionHelper 依赖项移到工厂中。
  3. 静态记录器也应该剥离到一个接口(interface)中,一个实例也应该注入(inject)到您的 Authenticator 中,它的生命周期也由您的 IoC 容器管理。 LoggerEntitiesFactory 都可以注入(inject)

你应该得到类似下面的结果:

  public interface IEntitiesFactory
{
Entities Create();
}

public interface ILog
{
void LogLine(TraceLevel level, string message);
}

class Authenticator : IAuthenticator
{
private readonly IEntitiesFactory _entitiesFactory;
private readonly ILog _log;

public Authenticator(IEntitiesFactory entitiesFactory, ILog log)
{
_entitiesFactory = entitiesFactory;
_log = log;
}

public string UserId { get; set; }
public string Password { get; set; }
public UserModel User { get; private set; }

public bool ValidateUser()
{
if (string.IsNullOrEmpty(UserId))
return false;

if (string.IsNullOrEmpty(Password))
return false;

using (var db = _entitiesFactory.Create())
{
MD5 md5 = MD5.Create();
byte[] inputBytes = Encoding.ASCII.GetBytes(this.Password);
byte[] hash = md5.ComputeHash(inputBytes);
string md5Hash = BitConverter.ToString(hash).ToUpper().Replace("-", string.Empty);

var query = from u in db.Users
where u.UserId.ToUpper().Trim() == this.UserId.ToUpper()
where u.CPassword.Trim() == md5Hash
select u;

this.User = query.FirstOrDefault();
}

if (this.User == null)
{
_log.LogLine(TraceLevel.Verbose, string.Format("Authentication failed for user '{0}'", this.UserId));
return false;
}
else
{
_log.LogLine(TraceLevel.Verbose, string.Format("Successfully authenticated user '{0}'", this.UserId));
return true;
}
}

,您现在可以在这里 Mock 实体工厂和记录器,现在为找到/未找到的场景提供假的 Users 数据,并验证正确的东西被发送到 logger 等,即

 [Test]
public void SomeTest()
{
var mockFactory = new Mock<IEntitiesFactory>();
var mockEntities = new Mock<Entities>();
var fakeUsers = new List<UserModel>
{
new UserModel
{
UserId = "Bob",
CPassword = "TheHashOfSecret"
}
};
mockEntities.SetupGet(_ => _.Users).Returns(fakeUsers.AsQueryable());
mockFactory.Setup(_ => _.Create()).Returns(mockEntities.Object);
var mockLog = new Mock<ILog>();
var sut = new Authenticator(mockFactory.Object, mockLog.Object)
{
UserId = "Bob",
Password = "Secret"
};
Assert.DoesNotThrow(() => sut.ValidateUser());
Assert.IsNotNull(sut.User);
mockLog.Verify(_ => _.LogLine(), Times.Once); ...
}

关于c# - 如何正确测试这个? (C#、NUnit、最小起订量),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22691470/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com