简体   繁体   English

单元测试失败-Moq不调用方法

[英]Unit Test Failing - Moq Not Invoking Method

Given the following, why does this unit test fail saying: 给定以下内容,为什么这个单元测试失败说:

Expected invocation on the mock once, but was 0 times: x => x.Steps.Remove(It.IsAny()) 预期对该模拟调用一次,但被调用0次:x => x.Steps.Remove(It.IsAny())

Configured setups: 配置的设置:

x => x.Steps.Remove(It.IsAny<Step>()), Times.Never
No invocations performed.

Code : 代码

public static SubmissionVersion DeleteStep(IRepository repository, SubmissionVersion version, Guid stepId)
    {
        Step step = repository.GetById<Step>(stepId);
        Level level = step.Level;

        /// Delete child objects
        Step.DeleteNotifications(repository, step);

        /// Delete Step
        version.Steps.Remove(step);
        repository.Save(version);
        repository.Delete(step);

        /// Reorder Levels
        IList<Level> levels = new List<Level>();
        version.Steps.Where(s => s != step).OrderBy(s => s.Level.SortOrder).ForEach(s =>
        {
            if (!levels.Contains(s.Level))
                levels.Add(s.Level);
        });

        Level prevLevel = null;
        levels.ForEach(lvl =>
        {
            if (prevLevel != null)
            {
                lvl.DependsOnLevel = prevLevel;
                repository.Save(lvl);
            }
            prevLevel = lvl;
        });

        /// Delete Level
        if (!levels.Contains(level))
            repository.Delete(level);


        int order = 0;
        List<Step> sorted = version.Steps.OrderBy(c => c.SortOrder).ToList();
        sorted.ForEach(c =>
        {   /// Update SortOrder for list items
            c.SortOrder = order++;
            repository.Save(c);
        });
        return repository.GetById<SubmissionVersion>(version.Id);
    }

Test 测试

[Fact]
public void Should_Call_SubmissionVersionRemoveStepsOnce()
{
    // Arrange
    var ctx = new TestContext();
    ctx
        .SubmissionVersion
        .SetupGet(x => x.Steps)
        .Returns(new List<Step> { ctx.Step });

    // Act
    SubmissionVersion.DeleteStep(
        ctx.Repository.Object,
        ctx.SubmissionVersion.Object,
        ctx.Step.Id.Value);

    // Assert
    ctx
        .SubmissionVersion
        .Verify(x => x.Steps.Remove(It.IsAny<Step>()), Times.Once());
}

TestContext : TestContext

internal class TestContext
{
    // Objects
    public Note Note { get; private set; }
    public Section Section { get; private set; }
    public Step Step { get; private set; }
    public SubmissionVersionProjectType SubmissionVersionProjectType
        { get; private set; }
    public SubmissionVersionStatusHistory SubmissionVersionStatusHistory
        { get; private set; }

    // Mocks
    public Mock<SubmissionVersion> SubmissionVersion { get; private set; }
    public Mock<IRepository> Repository { get; private set; }

    public TestContext()
    {
        Note = new Note { Id = Guid.NewGuid() };
        Section = new Section { Id = Guid.NewGuid(), SortOrder = 0 };
        Step = new Step() { Id = Guid.NewGuid() };
        SubmissionVersionProjectType
            = new SubmissionVersionProjectType { Id = Guid.NewGuid() };
        SubmissionVersionStatusHistory
            = new SubmissionVersionStatusHistory { Id = Guid.NewGuid() };

        SubmissionVersion = new Mock<SubmissionVersion>();
        SubmissionVersion.Setup(x => x.Id).Returns(Guid.NewGuid());
        SubmissionVersion.Setup(x => x.Notes.Remove(Note));
        SubmissionVersion.Setup(x => x.Sections.Remove(Section));
        SubmissionVersion.Setup(x => x.Steps.Remove(It.IsAny<Step>()));
        SubmissionVersion.Setup(x => x.SubmissionVersionProjectTypes.Remove(SubmissionVersionProjectType));
        SubmissionVersion.Setup(x => x.SubmissionVersionStatusHistory.Remove(SubmissionVersionStatusHistory));

        Repository = new Mock<IRepository>();
        Repository.Setup(x => x.GetById<Note>(Note.Id)).Returns(Note);
        Repository.Setup(x => x.GetById<Section>(Section.Id)).Returns(Section);
        Repository.Setup(x => x.GetById<Step>(Step.Id)).Returns(Step);
        Repository.Setup(x => x.GetById<SubmissionVersionProjectType>(SubmissionVersionProjectType.Id)).Returns(SubmissionVersionProjectType);
        Repository.Setup(x => x.GetById<SubmissionVersionStatusHistory>(SubmissionVersionStatusHistory.Id)).Returns(SubmissionVersionStatusHistory);
        Repository.Setup(x => x.GetById<SubmissionVersion>(SubmissionVersion.Object.Id)).Returns(SubmissionVersion.Object);
    }
}

I think you missing a Setup. 我认为您缺少安装程序。 Moq would know the .Steps (you already have setup on this), but it would not know the .Remove. Moq会知道.Steps(您已经对此进行了设置),但是不知道.Remove。

   ctx.SubmissionVersion.Setup(x => x.Steps.Remove(It.IsAny<Step>()));

So your test would be.. 所以你的测试是

    [Fact]
    public void Should_Call_SubmissionVersionRemoveStepsOnce()
    {
        // Arrange
        var ctx = new TestContext();
        ctx
            .SubmissionVersion
            .SetupGet(x => x.Steps)
            .Returns(new List<Step> { ctx.Step });
        var submissionVersion = ctx.SubmissionVersion.Object;

        ctx.SubmissionVersion.Setup(x => x.Steps.Remove(It.IsAny<Step>()));

        // Act
        submissionVersion.DeleteStep(
            ctx.Repository.Object,
            ctx.SubmissionVersion.Object,
            ctx.Step.Id.Value);

        // Assert
        ctx
            .SubmissionVersion
            .Verify(x => x.Steps.Remove(It.IsAny<Step>()), Times.Once());
    }

Now you remove the Steps.Remove or call more than once from your SUT (submissionVersion), the test would fail. 现在您删除Steps.Remove或从您的SUT(submissionVersion)调用不止一次,测试将失败。 Calling only once the test would pass. 测试只通过一次即可调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM