解惑

解己之惑,解人之惑

标签:单元测试

单元测试以Windows集成方式认证的Web Service

如果直接引用Web Service写单元测试,运行以Windows集成方式认证并且不允许匿名访问的Web Service,那么运行的时候会报错,因为权限不够,可能是因为Visual Studio在运行的时候是以匿名用户的身份运行的,而非OS的用户身份,这样的情况需要写些代码来使用OS的用户身份:
        [TestInitialize]
        public void SetUp()
        {
            var basicHttpBinding = new BasicHttpBinding();

            basicHttpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;

            basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

            var endpoint = new EndpointAddress("http://localhost/IntegrationService/IntegrationService.asmx");

            _client = new IntegrationServiceSoapClient(basicHttpBinding, endpoint);
            _client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

            _client.ChannelFactory.Credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
        }
代码中的EndpointAddress和IntegrationServiceSoapClient要换成你自己的Web Service的对应内容。

更新:
如果按照 Windows平台应用的运行身份的更新中所说的指定用户,那么这里的单元测试就不需要这样麻烦了,直接new一个Client就可以了。

总算是初步完成了EJB单元测试框架

经过一段时间的努力,我总算是初步完成了这个EJB单元测试框架,现在运行那些测试用例(183个,难易不等)只需要60秒左右,我挑选出来的一个做为样例的Session Bean的代码行覆盖率达到94%,而Branch覆盖率为100%。
明天计划说服其它的人使用这个框架辅助他们的开发,虽然这个是单元测试,但是因为不用启动JBoss也可以调试Session Bean和Action,我想使用它辅助开发也是个不错的主意(我们的JBoss启动需要至少2分钟,一般都是在3分钟以上)。另外一个进行辅助开发的原因是我们的时间很紧,原本计划在这个版本中要求新的功能必须有单元测试的要求可能也要取消了,那我辛辛苦苦完成的框架可能要拖到至少明年3月以后才可能被使用了,夜长梦多啊。
另外一个考虑就是他们写的测试用例越多,可能发现的问题也越多,也好帮助我更加完善这个框架。另外就是可能会要求我增加更多的功能辅助他们的验证工作。

艰难的过程

最近在做公司的单元测试框架,本来感觉已经初具规模,可以开始正常的使用了,因为我写了40多个各种类型的测试用例都可以正常工作,另外一个组的同事开始写了一个,他说还是挑的一个最简单的,结果报了一堆的异常,呵呵,其实他是测试Message Driven Bean,代码里面要调用很多其它的东西,出了几个问题,一个是他要使用的一个Entity Bean的finder是我写的表达式不支持的,我只能把那个finder实现掉,然后就是代码中使用了一个Topic,而且不是我们的Server端代码使用的,没有对应的Message Driven Bean处理(框架只能自动发布有对应的Message Driven Bean的Queue或者Topic),这个问题忽略不计了,因为那个Message本来就不需要处理,然后就是另外一个finder方法,我的表达式是支持的,但是死活找不到,结果发现是那个Entity Bean的xdoclet的配置比较特殊,一般的Home接口都是Remote接口的名字加Home,结果那个Bean是加BeanHome,而Aspect的匹配表达式是默认的格式,没有办法,修改我的表达式了,谁让那个Home接口的名字是可配置的呢。
另外两个问题还没有搞定,一个是Stateless Session Bean的remove方法,不知道要做什么,我现在处理了Entity Bean的remove,调用那个的时候会从数据库中删除对应的记录,但是Stateless Session Bean的remove应该做什么呢?
一个是获得Topic,我们的那个Locator接口里面定义了获得各种Bean以及Queue的接口方法,但是没有定义获得Topic的方法,所以代码中都是使用:
Context jndiContext = new InitialContext();
topic = (Topic) jndiContext.lookup(serverDataSendTopicName);
这个lookup的过程框架拦截不到。

MockEJB测试框架之自动发布EJB

前段时间大致介绍了下这个测试框架,目前还没有完全完成,这里先慢慢介绍下框架得构成,这个是第一篇。

其实MockEJB提供的功能还是比较简单的,做单元测试需要我们自己写代码发布Bean,例如发布一个Session Bean:
            SessionBeanDescriptor sampleServiceDescriptor =
                new SessionBeanDescriptor( SampleService.JNDI_NAME,
                SampleServiceHome.class, SampleService.class, new SampleServiceBean() );
             mockContainer.deploy( sampleServiceDescriptor );

其实每个EJB工程都应该有现成的EJB配置文件(ejb-jar.xml、jboss.xml、jbosscmp-jdbc.xml),因此这个发布工作应该可以自动完成,思路就是自己读取那些配置文件获得EJB的配置信息。
然后就是要修改lookup的过程,由于我们的工程提供一个共通的接口来进行lookup,所以问题就演变为实现一个那个接口。对于其它的项目,应该是类似的,如果是直接使用Context的lookup,那么对于MockEJB而言就是扩展MockContext,覆盖lookup方法,先查找,找到目标就返回,没有的话尝试根据读取的EJB配置信息自动发布需要的EJB。这样,我们就在单元测试中可以直接获取EJB,而不用再进行发布了。

EJB单元测试框架

公司的产品要引入单元测试以及代码覆盖,让我做一个框架方便我们写单元测试代码,上网找了一下,找到一个不错的基础:MockEJB,大家可以先了解下相关的内容:
MockEJB项目简介信息
使用MockEJB简化EJB测试

我在这个基础上进行了扩充,框架具有如下的特性:

  • 读取EJB配制文件完成EJB的自动发布,框架会读取我们工程的ejb-jar.xml,jboss.xml,jbosscmp- jdbc.xml文件的配制信息并组合这些信息完成自动发布所需要的内容。
  • 共享的dummy数据,我们自己提供一个xml文件,里面存放一些dummy的数据,这些数据会在对应的Entity Bean被使用的时候自动插入数据库,完成数据的初始化工作(这样Session Bean中的SQL也可以取到一致的内容),在一个test方法结束的时候回滚,删除那些记录,消除Test Case之间的影响。
  • 自定义事务管理,每个test方法都处于同一个事务中,方法结束的时候事务回滚,消除Test Case之间的影响。
  • 支持部分find方法的实现,由于MockEJB对于Entity Bean只提供了对findByPrimaryKey的支持,甚至连findAll都不支持,框架在MockEJB提供的Aspect机制的基础上实现了 findAll等常用必备的find方法,并且对于自定义的find方法也提供部分支持,通过解析EJB配制文件中的SQL完成,但是可能性能不好,因为会遍历所有的记录并比较字段的值完成这个查找的过程。其它比较复杂的find方法(框架无法解析的SQL),需要自己实现对应的Aspect,框架会自动查找对应的Aspect。
  • Struts TestCase的基础上支持对Action的单元测试。

测试代码范例:
阅读全文

© 2024 解惑

本主题由Anders Noren提供向上 ↑