在Justmock中模拟构造函数调用对于UrlHelper失败

时间:2016-09-30 09:14:36

标签: c# asp.net-mvc unit-testing mocking justmock

在justmock中,我们可以通过像

那样排列构造函数调用来返回模拟实例而不是实际实例
Mock.Arragne(()=>new MyClass(Arg.IsAny<string>())).IgnoreInstance().Returns(Mock.Create<MyClass>());

但是当我尝试使用UrlHelper类而不是模拟类型时,实际类型正在实例化。任何人都可以告诉我这里是否有任何错误:

UrlModel类

    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 .. 
}

3 个答案:

答案 0 :(得分:1)

您可以使用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);
}

答案 1 :(得分:0)

您正在UrlHelper的构造函数中手动实例化UrlModel的实例。 UrlModel现已紧密耦合到UrlHelper new is 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 .. 

}

答案 2 :(得分:0)

在这种情况下构造函数模拟不起作用的唯一原因是UrlModel类已成为测试类的一部分 - 测试类中的代码本身不可模仿。

我想到的另一件事是你可能被调试器误导了。在运行探查器的情况下创建非抽象类型的模拟时,实例本身与模拟类型的类型相同 - 它不是派生类型,比如UrlHelperMock,因为它是分析器未运行时的情况。您能否使用调试器Make Object ID函数确认模拟实例和从new返回的实例真的不一样?

您是否得出结论new表达式嘲弄不起作用,因为您UrlHelper的安排不起作用,或者是其他内容?