2

鉴于以下情况,为什么这个单元测试失败说:

预期在模拟上调用一次,但为 0 次:x => x.Steps.Remove(It.IsAny())

配置的设置:

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

代码

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);
    }

测试

[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());
}

测试上下文

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);
    }
}
4

1 回答 1

1

我认为您缺少安装程序。Moq 会知道 .Steps(您已经对此进行了设置),但它不会知道 .Remove。

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

所以你的测试将是..

    [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());
    }

现在您从您的 SUT (submissionVersion) 中删除 Steps.Remove 或多次调用,测试将失败。仅在测试通过时调用。

于 2013-10-29T09:33:14.260 回答