如何测试一个抽象类的受保护的抽象方法? [英] How do I test an abstract class's protected abstract method?

查看:127
本文介绍了如何测试一个抽象类的受保护的抽象方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直工作在测试名为一个抽象类的最佳方式 TabsActionFilter 。我的存在保证从 TabsActionFilter 继承的类都会有所谓的方法 GetCustomer 。在实践中这种设计似乎运作良好。



在哪里我有一些问题是搞清楚如何测试 OnActionExecuted 基类的方法。这种方法依赖于在保护摘要 GetCustomer 方法的实现。我试着使用犀牛制品嘲讽类,但似乎无法嘲笑假客户从 GetCustomer 的回报。显然,翻转方法的公共的会使嘲讽可用,但的保护的感觉就像是比较合适的访问级别



有关的时间是我测试类我添加了从 TabsActionFilter 继承并返回一个伪造的客户对象的具体私有类。




  • 是一个具体的类的唯一选择?

  • 有没有嘲笑我失踪,允许犀牛制品,为<$ C回报的一种简单的机制$ C> GetCustomer ?



作为一个说明的安德森艾姆斯讨论这个他的意见在的约起订量,我可能会错过关键的东西,但它似乎并不适用在这里的答案。



类需要测试

 公共抽象类TabsActionFilter:ActionFilterAttribute 
{
公共覆盖无效OnActionExecuted(ActionExecutedContext filterContext)
{
客户的客户= GetCustomer(filterContext);

名单,LT; TabItem的>的TabItems =新的List<&TabItem的GT;();
tabItems.Add(CREATETAB(客户,摘要,详细信息,客户,
filterContext));
tabItems.Add(CREATETAB(客户,计算机,索引,机器,
filterContext));
tabItems.Add(CREATETAB(客户,帐户,为accountList,
客户,filterContext));
tabItems.Add(CREATETAB(客户,需要采取的行动,详细信息,
客户,filterContext));

filterContext.Controller.ViewData.PageTitleSet(customer.CustMailName);
filterContext.Controller.ViewData.TabItemListSet(的TabItems);
}

保护抽象客户GetCustomer(ActionExecutedContext filterContext);
}



测试类和嘲笑私人类

 公共类TabsActionFilterTest 
{
[TestMethod的]
公共无效CanCreateTabs()
{
//安排
VAR filterContext = GetFilterContext(); //方法不再赘述

TabsActionFilterTestClass tabsActionFilter =
新TabsActionFilterTestClass();

//行为
tabsActionFilter.OnActionExecuted(filterContext);

//断言
Assert.IsTrue(filterContext.Controller.ViewData
.TabItemListGet()计数方式> 0);
}

私有类TabsActionFilterTestClass:TabsActionFilter
{
保护覆盖客户GetCustomer(
ActionExecutedContext filterContext)
{
返回新客户
{
n =4242,
CustMailName =哈尔
};
}
}
}


解决方案

我认为你正在运行到的问题是,你的类是不可测试的,或者是不可测试不够。这当然是假设你已经正确地确定了GetCustomer确实是一件需要以孤立正确测试被嘲笑。



如果GetCustomer是一些需要为了正确地隔离和测试TabsActionFilter被嘲笑,你会以某种方式需要作出GetCustomer执行类的组合的一部分,而不是继承的方法。实现这一目标的最常用的方法是使用控制/依赖注入的反转。



所有这一切说,你的 COULD 的使用类似TypeMock来实现这一点。但是,当你遇到这样的地方一类难以测试的情况下,它通常是你的类有太多的责任,需要被分解成更小的组件的信号。



(我使用TypeMock FWIW不是一个球迷)。


I've been working on the best way to test an abstract class named TabsActionFilter. I've guranteed that classes that inherit from TabsActionFilter will have a method called GetCustomer. In practice this design seems to work well.

Where I've had some issues is figuring out how to test the OnActionExecuted method of the base class. This method relies upon the implementation of the the protected abstract GetCustomer method. I've tried mocking the class using Rhino Mocks but can't seem to mock the return of a fake customer from GetCustomer. Obviously, flipping the method to public will make mocking available, but protected feels like the more appropriate accessibility level.

For the time being in my test class I've added a concrete private class that inherits from TabsActionFilter and returns a faked Customer object.

  • Is a concrete class the only option?
  • Is there a simple mechanism of mocking that I'm missing that would allow Rhino Mocks to provide a return for GetCustomer?

As a note Anderson Imes discusses his opinions on this in an answer about Moq and I could be missing something key, but it doesn't seem applicable here.

Class that needs to be tested

public abstract class TabsActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Customer customer = GetCustomer(filterContext);

        List<TabItem> tabItems = new List<TabItem>();
        tabItems.Add(CreateTab(customer, "Summary", "Details", "Customer",
            filterContext));
        tabItems.Add(CreateTab(customer, "Computers", "Index", "Machine",
            filterContext));
        tabItems.Add(CreateTab(customer, "Accounts", "AccountList",
            "Customer", filterContext));
        tabItems.Add(CreateTab(customer, "Actions Required", "Details",
            "Customer", filterContext));

        filterContext.Controller.ViewData.PageTitleSet(customer.CustMailName);
        filterContext.Controller.ViewData.TabItemListSet(tabItems);
    }

    protected abstract Customer GetCustomer(ActionExecutedContext filterContext);
}

Test Class and Private Class for "mocking"

public class TabsActionFilterTest
{
    [TestMethod]
    public void CanCreateTabs()
    {
        // arrange
        var filterContext = GetFilterContext(); //method omitted for brevity

        TabsActionFilterTestClass tabsActionFilter =
            new TabsActionFilterTestClass();

        // act
        tabsActionFilter.OnActionExecuted(filterContext);

        // assert
        Assert.IsTrue(filterContext.Controller.ViewData
            .TabItemListGet().Count > 0);
    }

    private class TabsActionFilterTestClass : TabsActionFilter
    {
        protected override Customer GetCustomer(
            ActionExecutedContext filterContext)
        {
            return new Customer
            {
                Id = "4242",
                CustMailName = "Hal"
            };
        }
    }
}

解决方案

I think the problem you are currently running into is that your class is not testable, or is not testable enough. This is of course assuming that you have correctly identified that GetCustomer is indeed something that needs to be mocked in order to properly test in isolation.

If GetCustomer is something that needs to be mocked in order to properly isolate and test TabsActionFilter, you will somehow need to make the implementation of GetCustomer a composable part of the class, and not an inherited method. The most common way to achieve this is to use Inversion of Control/Dependency Injection.

All that said, you COULD use something like TypeMock to achieve this. However, when you encounter a situation like this where a class is hard to test, it is usually a signal that your class has too many responsibilities and needs to be broken into smaller components.

(I am not a fan of using TypeMock FWIW).

这篇关于如何测试一个抽象类的受保护的抽象方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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