简体   繁体   English

Moq以验证某些不可预测的值

[英]Moq to verify certain value not predicable

To make it easy to explain, I have following codes 为了易于解释,我有以下代码

public interface IAnother
{
    void DoAnotherJob(DateTime date);
}

public class MainJob
{
    private IAnother another;

    public MainJob(IAnother another)
    {
        this.another = another;
    }

    public void FunctionA()
    {
        this.FunctionB(DateTime.Now);
    }

    public void FunctionB(DateTime date)
    {
        this.another.DoAnotherJob(date);
    }
}

I need to write a unit test code to make sure when FunctionA() is called the underlying IAnother.DoAnotherJob() is called to use the current date time. 我需要编写一个单元测试代码,以确保何时调用FunctionA()来调用基础IAnother.DoAnotherJob()来使用当前日期时间。

I can write the testing code 我可以编写测试代码

    [TestMethod()]
    public void FunctionATest()
    {
        var mockAnother = new Mock<IAnother>();

        var mainJob = new MainJob(mockAnother.Object);

        mainJob.FunctionA();

        mockAnother.Verify(x => x.DoAnotherJob(It.IsAny<DateTime>()), Times.Once);
    }

to make sure the function is called with any date time, but I have no way to specify the exact value since the real value of DateTime is not predictable. 以确保函数使用任何日期时间进行调用,但是由于DateTime的实际值是不可预测的,因此我无法指定确切的值。

Any ideas? 有任何想法吗?

You are always going to struggle when you want to verify anything regarding DateTime.Now as the property value will most likely change between calls. 要验证有关DateTime.Now任何内容时,您总是会费劲。现在,属性值很可能在两次调用之间发生变化。 The best you can do is something like this: 您可以做的最好的事情是这样的:

mockAnother.Verify(x => x.DoAnotherJob(It.Is<DateTime>(d > DateTime.Now.AddSeconds(-1))), Times.Once);

The alternative is to introduce another class and abstraction which you use to resolve the DateTime : 替代方法是引入另一个类和抽象,以用于解析DateTime

public interface ITimeProvider
{
    DateTime Now { get; }
}

public class TimeProvider : ITimeProvider
{
    DateTime Now { get { return DateTime.Now ; } }
}

Which you would then use instead of DateTime.Now directly: 然后直接使用它代替DateTime.Now

public class MainJob
{
    private IAnother another;
    private ITimeProvider timeProvider;

    public MainJob(IAnother another, ITimeProvider timeProvider)
    {
        this.another = another;
        this.timeProvider = timeProvider;
    }

    public void FunctionA()
    {
        this.FunctionB(this.timeProvider.Now);
    }

    public void FunctionB(DateTime date)
    {
        this.another.DoAnotherJob(date);
    }
}

Then, your Unit Test becomes: 然后,您的单元测试将变为:

[TestMethod()]
public void FunctionATest()
{
    var now = DateTime.Now;
    var mockAnother = new Mock<IAnother>();
    var mockTimeProvider = new Mock<ITimeProvider>();
    mockTimeProvider.Setup(x => x.Now).Returns(now);

    var mainJob = new MainJob(mockAnother.Object, mockTimeProvider.Object);

    mainJob.FunctionA();

    mockAnother.Verify(x => x.DoAnotherJob(now), Times.Once);
}

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

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