[英]Unit Testing a CRUD operation of a Repository - function which routes to test or live DB based on HttpContext is making testing difficult
目前,我们正在开发一个利用类库的新项目。 我正在开发该站点的功能,致力于存储库的基础,该存储库现在具有与数据库通信的简单CRUD操作方法。 我们最近决定开始尝试对我们的代码进行单元测试,以进一步鼓励良好的编程习惯。
现在,我的单元测试失败了,因为它试图在Live DB上使用存储过程-Live上当前不存在该存储过程。 最初,它只是失败了(引发了一个异常),我欺骗了HttpContext并将其传递给服务器名称URL,该URL应该触发连接到测试数据库。 但是,它正在连接到当前正在运行的代码,我相信导致该问题的代码是:
public static bool TestMode()
{
if (
HttpContext.Current.Request.ServerVariables["SERVER_NAME"] == "localhost" ||
HttpContext.Current.Request.ServerVariables["SERVER_NAME"] == "test.org"
)
return true;
else
return false;
}
该库旨在与MVC站点结合使用,因此并不需要这种类型的设置,不幸的是,在重构我们的操作方式时,这不是我的选择。
有人说这是我的单元测试
[TestClass]
public class CalendarTests {
public CalendarRepository _repo { get; set; }
[TestInitialize]
public void Setup() {
_repo = new CalendarRepository();
HttpContext.Current = new HttpContext(
new HttpRequest(null, "http://test.org", null),
new HttpResponse(null)
);
}
[TestMethod]
public void CreateEventTest() {
int val = _repo.CreateEvent(1,
"test title",
"demo-description",
DateTime.Now,
DateTime.Now.AddDays(1),
true,
1,
1);
Assert.IsTrue(val > 0);
}
}
我完成的大多数搜索都遇到了这个问题,因为他们正在测试MVC项目上的控制器,但是这略有不同,我不确定从何而来。 我知道我需要找到一种方法来模拟上下文以进行测试。 建议使用各种测试框架,例如NUnit,以及模拟框架,例如NSubstitute。 我对此有兴趣,但不确定是否可以使用它们。
任何和所有帮助表示赞赏!
编辑:
我试过的
编辑2:
这是连接字符串来自的地方
public static string DSHA()
{
var db = new Database()
{
LiveConnectionString = "sanitized-live",
TestConnectionString = "sanitized-test"
};
return ResolveConnection(db);
}
这是TestMode调用的代码
private static string ResolveConnection(Database db)
{
if (Helpers.TestMode())
return db.TestConnectionString;
else
return db.LiveConnectionString;
}
因此,我要求提供连接字符串,该字符串称为DSHA,从而导致来自ResolveConnection的评估,其条件是TestMode,最终决定了返回的连接字符串。
编辑2:
Nkosi的答复非常令人愉快,但是现在我正在尝试确保Helpers获取服务器真正提供的默认ServerVariables。 我试图使用构造函数
public Helpers(){
ServerVariable = new ServerVariables();
}
但是,当我在单元测试中检查Context时,我得到一个null引用异常,这是因为Helpers具有静态方法,但Helpers类本身不是静态的。
[TestMethod]
public void CheckContext(){
var context = Helpers.ServerVariable.Name;
Assert.IsTrue(context == "localhost");
}
我不确定使用容器注入接口的正确方法,但是要避免尽可能多地更改Helpers类的行为,因为有很多使用它编写的代码。 需要提供其他任何东西可能意味着要进行大量搜索以确保它的行为在任何地方都可以改变。
从注释中可以看出,您基本上需要从HttpContext
获取服务器名称。
在包装HttpContext
的服务背后抽象该功能,并为您提供所需的内容。
就像是...
public interface IServerVariable {
string Name { get; }
}
你可以有一个实现...
public class ServerVariables : IServerVariable {
public string Name {
get {
return HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
}
}
}
可以根据需要IServerVariable
进行测试。 因此,可以直接注入接口以获取所需的数据,而不是直接引用HttpContext
。
您可能需要重构当前代码,以允许通过容器注入接口,否则您将不得不手动进行操作。 但是除此之外,这还应该使您的代码更具可测试性。
假设...
public class Helpers {
public static IServerVariable ServerVariable {get;set;}
public static bool TestMode()
{
if (ServerVariable != null
&& (ServerVariable.Name == "localhost" || ServerVariable.Name == "test.org")
)
return true;
else
return false;
}
}
测试可能看起来像...
[TestClass]
public class CalendarTests {
private class FakeServerVariable : IServerVariable {
public string Name { get { return "test.org"; }
}
public CalendarRepository _repo { get; set; }
[TestInitialize]
public void Setup() {
_repo = new CalendarRepository();
Helpers.ServerVariable = new FakeServerVariable();
}
[TestMethod]
public void CreateEventTest() {
int val = _repo.CreateEvent(1,
"test title",
"demo-description",
DateTime.Now,
DateTime.Now.AddDays(1),
true,
1,
1);
Assert.IsTrue(val > 0);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.