在Justmock中对UrlHelper的mock构造函数调用失败

本文关键字:函数调用 失败 mock Justmock 中对 UrlHelper | 更新日期: 2023-09-27 18:09:33

在justmock中,我们可以通过安排构造函数调用来返回模拟实例而不是实际实例,如

Mock.Arragne(()=>new MyClass(Arg.IsAny<string>())).IgnoreInstance().Returns(Mock.Create<MyClass>());

但是当我尝试与UrlHelper类相同时,而不是模拟类型,实际类型正在实例化。谁能告诉我这里是否有错误?

UrlModel class

    public class UrlModel
    {
        private UrlHelper url;
        public UrlModel()
        {
           url = new UrlHelper(HttpContext.Current.Request.RequestContext);
        }
    }

试验方法:

public void UrlTest()
{
   Mock.Arrange(() => HttpContext.Current.Request.RequestContext).Returns(Mock.Create<RequestContext>());
    var mockedUrl = Mock.Create<UrlHelper>();
    Mock.Arrange(() => new UrlHelper(Arg.IsAny<RequestContext>()))
        .IgnoreArguments()
        .IgnoreInstance()
        .Returns(mockedUrl);
    //Here url will have actual instance instead of mocked instance
    var model = new UrlModel();
    //Assert is ommitted for bravity .. 
}

在Justmock中对UrlHelper的mock构造函数调用失败

您可以使用Typemock来测试您的代码,而无需添加任何新的接口,通过伪造RequestContext并修改属性行为:

[TestMethod,Isolated]
public void UrlTest()
{
    //Arrange 
    var fakeRequest = Isolate.Fake.Instance<RequestContext>();
    Isolate.WhenCalled(() => HttpContext.Current.Request.RequestContext).WillReturn(fakeRequest);
    //Act
    var res = new UrlModel();
    //getting the private field so it can be asserted
    var privateField = Isolate.NonPublic.InstanceField(res, "url").Value as UrlHelper;
    //Assert
    Assert.AreEqual(fakeRequest, privateField.RequestContext);
}

您正在UrlModel的构造函数中手动实例化UrlHelper的实例。UrlModel现在与UrlHelper紧密耦合(新的是glue)。创建一个依赖抽象,允许更松散耦合的模型和改进的模拟能力

public interface IUrlHelperAccessor {
    UrlHelper UrlHelper { get; }
}

注入UrlModel

public class UrlModel {
    private UrlHelper url;
    public UrlModel(IUrlHelperAccessor accessor) {
       url = accessor.UrlHelper;
    }
    //...other code
}

现在你安排相应的测试

public void UrlTest() {
    Mock.Arrange(() => HttpContext.Current.Request.RequestContext)
        .Returns(Mock.Create<RequestContext>());
    var mockedUrl = Mock.Create<UrlHelper>(Constructor.Mock);
    var mockedAccessor = Mock.Create<IUrlHelperAccessor>();
    Mock.Arrange(() => mockedAccessor.UrlHelper).Returns(mockedUrl);
    //Here url will have actual instance instead of mocked instance
    var model = new UrlModel(mockedAccessor);
    //Assert is omitted for brevity .. 
}

在这种情况下构造函数mock不能工作的唯一原因是UrlModel类是测试类的一部分——测试类中的代码本身是不可mock的。

想到的另一件事是,您可能被调试器误导了。当您在运行剖析器的情况下创建非抽象类型的模拟时,实例本身的类型与模拟类型相同—它不是派生类型,例如UrlHelperMock,这是剖析器未运行时的情况。您可以使用调试器Make Object ID函数确认模拟实例和从new返回的实例确实不一样吗?

你得出的结论是,new的表达嘲讽不起作用,因为你的UrlHelper的安排不起作用,或者是别的什么?