【发布时间】:2014-12-30 01:23:00
【问题描述】:
我正在同一个类中尝试模拟内部方法。但是我的模拟失败了。
这是我的代码。
界面
public interface IStudentService
{
int GetRank(int studentId);
IList<Subject> GetSubjects(int studentId);
}
实施
public class StudentService : IStudentService
{
private readonly IStudentRepository _studentRepository;
private readonly ISubjectRepository _subjectRepository;
public StudentService(IStudentRepository studentRepository, ISubjectRepository subjectRepository)
{
_studentRepository = studentRepository;
_subjectRepository = subjectRepository;
}
public int GetRank(int studentId)
{
IList<Subject> subjects = GetSubjects(studentId);
int rank = 0;
//
//Calculate Rank
//
return rank;
}
public virtual IList<Subject> GetSubjects(int studentId)
{
return _subjectRepository.GetAll(studentId);
}
}
单元测试
[TestFixture]
public class StudentServiceTest
{
[SetUp]
public void Setup()
{
}
[TearDown]
public void TearDown()
{
}
[Test]
public void GetRankTest()
{
using (var mock = AutoMock.GetStrict())
{
var mockStudentService = new Mock<IStudentService>();
mockStudentService.Setup(x => x.GetSubjects(1)).Returns(new ServiceResponse<SystemUser>(new List<Subject>{ new AccounProfile(), new AccounProfile()}));
mock.Provide(mockStudentService.Object);
var component = mock.Create<StudentService>();
int rank = component.GetRank(1);
mockStudentService.VerifyAll();
Assert.AreEqual(1, rank, "GetRank method fails");
}
}
}
当我调试代码时,它不是在模拟 GetSubjects 方法。它实际上进入了那个方法。我正在使用 Nunit、Moq 和 Autofac 编写单元测试。
提前致谢!
【问题讨论】:
-
既然可以轻松地模拟存储库,为什么还要尝试模拟内部方法?吉米做对了:)
-
如果 GetSubject 方法有多个存储库方法,那么我必须全部模拟它们。此外,如果 GetSubjects 方法有来自同一类的另一个方法,我也必须模拟它们。因此,除了我正在测试的方法之外,我还必须模拟很多东西。 Autofac 是否支持部分模拟?
-
首先,Autofac 是一个 DI 框架,根本与模拟无关。在您的示例中,您可以删除 Autofac 的所有痕迹,并且仍然可以使用模拟编写测试。事实上,我总是用尽可能少的额外框架编写测试:新建一个
StudentService实例并传入两个模拟存储库。是的,在测试一段代码时,您必须模拟外部依赖项,在您的情况下是存储库。如果您觉得发生的事情太多,也许这表明您的服务做得太多:然后将其拆分为更细化的服务! -
...建议:阅读更多关于什么是模拟的信息,例如这个帖子很好stackoverflow.com/questions/2665812/what-is-mocking
标签: c# unit-testing nunit moq autofac