如何注入用于 Moq 的模拟程序集 [英] How to inject a mock Assembly for use with Moq

查看:39
本文介绍了如何注入用于 Moq 的模拟程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的控制器中有一个方法可以将当前执行程序集中的属性数据返回到局部视图中.

在这个例子中,我只是拉取标题,但我需要做更多的事情.

控制器:

 var title = "";var asm = Assembly.GetExecutingAssembly();var attrs = asm.GetCustomAttributes(typeof(AssemblyTitleAttribute));var titleAttr = (AssemblyTitleAttribute)attributes[0];标题 = titleAttr.Title;return PartialView("_Build", title);

在 Moq 中编写单元测试时,我需要找到一种方法将 Assembly 属性注入到模拟中,以便我可以在运行控制器测试时验证是否正在生成正确的属性,然后执行 x 或 y用我的断言.

单元测试:

//排列//我需要发生的魔法.//行为var 控制器 = GetController();var result = controller.MyMethod() as PartialViewResult;var title = result.Model;//断言Assert.AreEqual("Title", title);//当前是静态的,需要针对模拟进行验证

我知道这是一组极其简单的代码,但此时我只需要概念证明.

有没有好方法来创建一个假程序集?我需要使用 System.Reflection.Emit 吗?

解决方案

您可以创建一个虚拟方法,例如GetCustomAttributes 提供给定类型的属性.然后在您的测试预测中,一个 testable 类将从控制器类派生并覆盖此方法.

<块引用>

家庭控制器:

私有IDependency _someDependency;公共家庭控制器(IDependency someDependency){_someDependency = someDependency;}公共 ActionResult MyMethod(){var title = "";var 版本 = "";IEnumerable<属性>属性 = GetCustomAttributes(typeof(AssemblyVersionAttribute)).ToList();AssemblyVersionAttribute verAttr = attributes.OfType().FirstOrDefault();if (verAttr != null) version = verAttr.Version;属性 = GetCustomAttributes(typeof(AssemblyTitleAttribute)).ToList();AssemblyTitleAttribute titleAttr = attributes.OfType().FirstOrDefault();if (titleAttr != null) title = titleAttr.Title;return PartialView("_Build", title + version);}公共虚拟 IEnumerable<属性>GetCustomAttributes(类型属性类型){var asm = Assembly.GetExecutingAssembly();var attrs = asm.GetCustomAttributes(attributeType);返回属性;}

<块引用>

测试:

[测试类]公共类 MyMethodTest{[测试方法]public void MyMethod_WhenCalled_PartialViewIsReturned(){//安排//我需要发生的魔法.Mock<IDependency>dependencyStub = new Mock();//dependencyStub.Setup(...).Returns(...);var controller = new TestableHomeController(dependencyStub.Object){UseFakeAttributes = true};//行为var result = controller.MyMethod() as PartialViewResult;//断言var 模型 = 结果.模型;Assert.AreEqual("MyFakeTitle1.0.0.0", 模型);//当前是静态的,需要针对模拟进行验证}私有类 TestableHomeController : HomeController{public bool UseFakeAttributes { get;放;}公共 TestableHomeController(IDependency someDependency):base(someDependency){ }公共覆盖 IEnumerable<属性>GetCustomAttributes(类型属性类型){返回 UseFakeAttributes?新列表<属性>{new AssemblyTitleAttribute("MyFakeTitle"),new AssemblyVersionAttribute("1.0.0.0"),new AssemblyDescriptionAttribute("组装假描述")//下一个属性...}.Where(a => a.GetType() == attributeType): base.GetCustomAttributes(attributeType);}}}

There is a method in my controller that returns attribute data from the current executing assembly into a partial view.

In this example, I'm merely pulling the Title, but I need to do more with it.

Controller:

    var title = "";

    var asm = Assembly.GetExecutingAssembly();
    var attrs = asm.GetCustomAttributes(typeof(AssemblyTitleAttribute));
    var titleAttr = (AssemblyTitleAttribute)attributes[0];

    title = titleAttr.Title;

    return PartialView("_Build", title);

When writing the unit test in Moq, I need to find a way to inject the Assembly attributes into a mock so that I can verify that the correct attributes are being generated when I run the controller test, and then do x or y with my asserts.

UnitTest:

    //Arrange
    //The magic I need to happen.

    //Act
    var controller = GetController();
    var result = controller.MyMethod() as PartialViewResult;
    var title = result.Model;

    //Assert
    Assert.AreEqual("Title", title); //currently static, need to verify against a mock

I know this is an extremely simple set of code, but I just need proof of concept at this point.

Is there a good way to create a fake Assembly? Do I need to use System.Reflection.Emit?

解决方案

You could create a virtual method e.g. GetCustomAttributes which provides the attributes for given type. Then in your test preject a testable class would derive from the controller class and override this method.

Home Controller:

private IDependency _someDependency;

public HomeController(IDependency someDependency)
{
    _someDependency = someDependency;
}

public ActionResult MyMethod()
{
    var title = "";
    var version = "";

    IEnumerable<Attribute> attributes = GetCustomAttributes(typeof(AssemblyVersionAttribute)).ToList();
    AssemblyVersionAttribute verAttr = attributes.OfType<AssemblyVersionAttribute>().FirstOrDefault();
    if (verAttr != null) version = verAttr.Version;

    attributes = GetCustomAttributes(typeof(AssemblyTitleAttribute)).ToList();
    AssemblyTitleAttribute titleAttr = attributes.OfType<AssemblyTitleAttribute>().FirstOrDefault();
    if (titleAttr != null) title = titleAttr.Title;

    return PartialView("_Build", title + version);
}

public virtual IEnumerable<Attribute> GetCustomAttributes(Type attributeType)
{
    var asm = Assembly.GetExecutingAssembly();
    var attrs = asm.GetCustomAttributes(attributeType);
    return attrs;
} 

Test:

[TestClass]
public class MyMethodTest
{
    [TestMethod]
    public void MyMethod_WhenCalled_PartialViewIsReturned()
    {
        // Arrange
        // The magic I need to happen.

        Mock<IDependency> dependencyStub = new Mock<IDependency>();
        // dependencyStub.Setup(...).Returns(...);
        var controller = new TestableHomeController(dependencyStub.Object)
        {
            UseFakeAttributes = true
        };

        // Act
        var result = controller.MyMethod() as PartialViewResult;

        // Assert
        var model = result.Model;
        Assert.AreEqual("MyFakeTitle1.0.0.0", model); // currently static, need to verify against a mock
    }

    private class TestableHomeController : HomeController
    {
        public bool UseFakeAttributes { get; set; }

        public TestableHomeController(IDependency someDependency)
            :base(someDependency)
        { }

        public override IEnumerable<Attribute> GetCustomAttributes(Type attributeType)
        {
            return UseFakeAttributes
                ? new List<Attribute>
                    {
                        new AssemblyTitleAttribute("MyFakeTitle"),
                        new AssemblyVersionAttribute("1.0.0.0"),
                        new AssemblyDescriptionAttribute("Assembly fake description")
                        // next attributes ...
                    }.Where(a => a.GetType() == attributeType)
                : base.GetCustomAttributes(attributeType);
        }
    }
}

这篇关于如何注入用于 Moq 的模拟程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆