我正在使用JustMock和Entity Framework来尝试为服务编写单元测试。在服务中,我有这个方法:
List<Log> GetLogType(string type)
{
using (var db = new LogContext())
{
return db.Logs.Where(x => x.Type == type).ToList();
}
}
我有一个测试:
[TestMethod]
public void GetLogTypeTest()
{
IList<Log> logs = new List<Log>
{
new Log() {
Id = 1,
Type = "Debug",
Message = "Test Message"
}
};
var logContext = Mock.Create<LogContext>(Constructor.Mocked).PrepareMock();
logContext.Logs.Bind(logs);
var service = new LogService();
var debugs = service.GetLogType("Debug");
Assert.AreEqual(1, debugs.Count());
}
如何让服务使用我的模拟上下文?现在它正在尝试连接到数据库,从而出错。
答案 0 :(得分:2)
<强>原因强>
由于JustMock
而未发生这种情况。之所以发生这种情况,是因为您在方法中创建了LogContext
的新实例。您的方法不是单元可测试的,因为它将始终创建新的服务实例并与真实数据库建立连接。有几个适用于C#的依赖注入框架,如果您有兴趣请查看Unity。
修复此
您必须使用依赖注入并在课堂中注入您的服务。在这种情况下,您可以避免连接到数据库。你的方法是这样的:
List<Log> GetLogType(string type)
{
return _logContext.Logs.Where(x => x.Type == type).ToList();
}
_logContext
是LogContext
类型的全局变量,通过构造函数注入。
你可以嘲笑它并传递mock trough构造函数。
班级的例子可以是:
public class LogService
{
private readonly LogContext _logContext;
public LogService(LogContext logContext)
{
_logContext = logContext;
}
List<Log> GetLogType(string type)
{
return _logContext.Logs.Where(x => x.Type == type).ToList();
}
}
现在您可以创建如下的测试用例:
[TestMethod]
public void GetLogTypeTest()
{
IList<Log> logs = new List<Log>
{
new Log() {
Id = 1,
Type = "Debug",
Message = "Test Message"
}
};
var logContext = Mock.Create<LogContext>(Constructor.Mocked).PrepareMock();
logContext.Logs.Bind(logs);
var service = new LogService(logContext);
var debugs = service.GetLogType("Debug");
Assert.AreEqual(1, debugs.Count());
}
请注意我做了什么。我像你一样创建了service
实例,但我注入了实际服务槽构造函数的模拟实例。模拟实例永远不会连接到数据库,它将返回您在配置中提供的数据。