2

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

3 回答 3

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);
}
于 2016-10-05T07:29:41.003 回答
0

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

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

你得出的结论是new嘲笑这个表达不起作用,是因为你的安排UrlHelper不起作用,还是别的什么?

于 2017-01-20T23:31:23.753 回答
0

您正在手动实例化UrlHelper的构造函数中的实例UrlModelUrlModel现在紧密耦合到UrlHelper新是胶水)。进行依赖抽象,您可以允许更松散耦合的模型和改进的模拟能力

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

}
于 2016-09-30T10:30:23.190 回答