Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Autofac为同一类中的内部方法编写Moq单元测试_C#_Unit Testing_Nunit_Moq_Autofac - Fatal编程技术网

C# 使用Autofac为同一类中的内部方法编写Moq单元测试

C# 使用Autofac为同一类中的内部方法编写Moq单元测试,c#,unit-testing,nunit,moq,autofac,C#,Unit Testing,Nunit,Moq,Autofac,我正在同一个类中尝试模拟内部方法,但模拟失败 这是我的密码 接口 public interface IStudentService { int GetRank(int studentId); IList<Subject> GetSubjects(int studentId); } 公共接口IStudentService { int GetRank(int studentId); IList GetSubjects(国际学生ID); } 实施 public clas

我正在同一个类中尝试模拟内部方法,但模拟失败

这是我的密码

接口

public interface IStudentService
{
    int GetRank(int studentId);
    IList<Subject> GetSubjects(int studentId);
}
公共接口IStudentService
{
int GetRank(int studentId);
IList GetSubjects(国际学生ID);
}
实施

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);
    }
}
公共班级学生服务:IStudentService
{
私人只读是学生档案库(studentRepository);
私有只读ISubjectRepository_subjectRepository;
公共学生服务(IStudentRepository studentRepository,ISubjectRepository subjectRepository subjectRepository)
{
_studentRepository=studentRepository;
_subjectRepository=subjectRepository;
}
公共int GetRank(int studentId)
{
IList受试者=获取受试者(studentId);
int秩=0;
//
//计算等级
//
返回等级;
}
公共虚拟IList GetSubjects(int studentId)
{
返回_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");
        }
    }
}
[TestFixture]
公共班级学生服务测试
{
[设置]
公共作废设置()
{
}
[撕裂]
公共无效拆卸()
{
}
[测试]
public void GetRankTest()
{
使用(var mock=AutoMock.GetStrict())
{
var mockStudentService=new Mock();
mockStudentService.Setup(x=>x.GetSubjects(1)).Returns(新服务响应(新列表{new accountupfile(),new accountupfile()}));
Provide(mockStudentService.Object);
var component=mock.Create();
int-rank=component.GetRank(1);
mockStudentService.VerifyAll();
AreEqual(1,rank,“GetRank方法失败”);
}
}
}
当我调试代码时,它不是在模仿GetSubjects方法。事实上,它深入到了这个方法中。我正在使用Nunit、Moq和Autofac编写单元测试


提前谢谢

我想您的
GetSubjects
方法必须声明为虚拟的,否则它不能被模仿

public virtual IList<Subject> GetSubjects(int studentId)
{
   // code here
} 
public虚拟IList GetSubjects(int studentId)
{
//代码在这里
} 

有两种解决方案

1.部分嘲弄 在这种方法中,您为正在测试的组件创建模拟(
StudentService
),并告诉Moq模拟它的一些方法(
GetSubjects
——要模拟的方法必须是虚拟的),同时将其他(
GetRank
)委托给:

设置
mock.CallBase=true
指示Moq将任何与显式
Setup
调用不匹配的调用委托给其基本实现


此代码适用于。谢谢大家的支持

[TestFixture]
public class StudentServiceTest
{
    private Mock<StudentRepository> _studentRepositoryMock;
    private Mock<SubjectRepository> _subjectRepositoryMock;
    private Mock<StudentService> _studentServiceMock;

    [SetUp]
    public void Setup()
    {
        _studentRepositoryMock = new Mock<StudentService>(MockBehavior.Strict);
        _subjectRepositoryMock = new Mock<SubjectRepository>(MockBehavior.Strict);
        _studentServiceMock = new Mock<StudentService>(_studentRepositoryMock.Object, _subjectRepositoryMock.Object);
        _studentServiceMock.CallBase = true;
    }

    [TearDown]
    public void TearDown()
    {

    }

    [Test]
    public void GetRankTest()
    {
        _studentServiceMock.Setup(x => x.GetSubjects(1)).Returns(...);

        int rank = component.GetRank(1);
        _studentServiceMock.VerifyAll();

        Assert.AreEqual(1, rank, "GetRank method fails");
    }
}   
[TestFixture]
公共班级学生服务测试
{
私人模拟(studentRepositoryMock),;
私人模拟(subject repositorymock);;
私人模拟——学生服务模拟;
[设置]
公共作废设置()
{
_studentRepositoryMock=newmock(MockBehavior.Strict);
_subjectRepositoryMock=新模拟(MockBehavior.Strict);
_studentServiceMock=新建Mock(_studentRepositoryMock.Object,_subjectRepositoryMock.Object);
_studentServiceMock.CallBase=true;
}
[撕裂]
公共无效拆卸()
{
}
[测试]
public void GetRankTest()
{
_studentServiceMock.Setup(x=>x.GetSubjects(1))。返回(…);
int-rank=component.GetRank(1);
_studentServiceMock.VerifyAll();
AreEqual(1,rank,“GetRank方法失败”);
}
}   

既然可以轻松模拟存储库,为什么还要尝试模拟内部方法?Jimmy说得对:)如果GetSubject方法有多个存储库方法,那么我必须模拟它们。此外,如果GetSubjects方法有来自同一类的另一个方法,我也必须模拟它们。因此,除了我正在测试的方法之外,我还必须模拟很多东西。Autofac是否支持部分mokcing?首先,Autofac是一个DI框架,与mocking完全无关。在这里的示例中,您可以删除Autofac的所有痕迹,并且仍然能够使用模拟编写测试。事实上,我总是使用尽可能少的额外框架编写测试:新建一个
StudentService
实例,并传入两个模拟存储库。是的,当测试一段代码时,您必须模拟外部依赖项,在您的例子中是存储库。如果您觉得正在进行的工作太多,那么这可能是您的服务做得太多的一个迹象:将其拆分为更细粒度的服务!。。。建议:阅读更多关于模拟的内容,例如,这个线程很好,我将该方法设置为虚拟,并使用CallBase=true进行了尝试,但没有成功:(在第二个解决方案中,如果GetSubject方法有多个存储库方法,那么我必须全部模拟它们。此外,如果GetSubjects方法有来自同一类的另一个方法,我也必须模拟它们。因此,除了我正在测试的方法之外,我还必须模拟很多东西。解决方案是什么?
using (var mock = AutoMock.GetStrict())
{
    var subjectRepositoryMock = new Mock<ISubjectRepository>();
    subjectRepositoryMock.Setup(x => x.GetSubjects(1)).Returns(...);
    mock.Provide(subjectRepositoryMock.Object);

    var component = mock.Create<StudentService>();
    int rank = component.GetRank(1);
    // verify is not needed once again

    Assert.AreEqual(1, rank, "GetRank method fails");
}
[TestFixture]
public class StudentServiceTest
{
    private Mock<StudentRepository> _studentRepositoryMock;
    private Mock<SubjectRepository> _subjectRepositoryMock;
    private Mock<StudentService> _studentServiceMock;

    [SetUp]
    public void Setup()
    {
        _studentRepositoryMock = new Mock<StudentService>(MockBehavior.Strict);
        _subjectRepositoryMock = new Mock<SubjectRepository>(MockBehavior.Strict);
        _studentServiceMock = new Mock<StudentService>(_studentRepositoryMock.Object, _subjectRepositoryMock.Object);
        _studentServiceMock.CallBase = true;
    }

    [TearDown]
    public void TearDown()
    {

    }

    [Test]
    public void GetRankTest()
    {
        _studentServiceMock.Setup(x => x.GetSubjects(1)).Returns(...);

        int rank = component.GetRank(1);
        _studentServiceMock.VerifyAll();

        Assert.AreEqual(1, rank, "GetRank method fails");
    }
}