目前,我们正在开发一个利用类库的新项目。我正在为该站点开发一个功能,处理存储库的基础知识,该存储库现在具有与数据库通信的简单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这样的模拟框架。我对这些产品感兴趣但不确定它们的使用是否合理。
感谢任何和所有帮助!
编辑:
我尝试过的事情:
虽然我删除了代码,但我尝试编写与this类似的代码以及this
EDIT2:
这是连接字符串来自
的位置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最终决定返回的连接字符串。
EDIT2:
Nkosi的回复非常有用,但是现在我正在尝试确保Helpers获得服务器真正提供的默认ServerVariables。我试图使用构造函数
public Helpers(){
ServerVariable = new ServerVariables();
}
然而,当我在单元测试中检查Context时,我得到一个空引用异常,我认为它是因为Helpers有静态方法,但是Helpers类本身并不是静态的。
[TestMethod]
public void CheckContext(){
var context = Helpers.ServerVariable.Name;
Assert.IsTrue(context == "localhost");
}
我不确定使用容器注入接口的正确方法,但是希望尽可能避免更改Helpers类的行为,因为使用它编写了相当多的代码。需要提供任何其他东西可能意味着相当多的狩猎,以确保它的行为随处可见。
答案 0 :(得分:1)
根据您指出的评论,您基本上需要从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);
}
}