dva1.0中的dva mockjs 用法如何使用还有.umirc.dva mockjs 用法如何配置

最近使用php开发项目,并用phpunit进行单元测试,使用phpunit的mock机制有一段时间了,决定记录使用经验,方便以后查阅。
public function testBit(){
$oClientMock = $this-&getMock('SomeClient'); // 创建mock对象
$oClientMock-&expects($this-&once()) // 设定次数
-&method('ExecuteCommand') // 设定方法
-&with(CPU_BIT_CMD) // 设定方法入参
-&will($this-&returnValue('some')); // 设定方法返回值
$oHardware = new MHardware($oClientMock);
$this-&assertEquals('32', $oHardware-&CpuBit()); // 调用方法并断言
简而言之,使用mock一般有下面几步:
getMock 创建mock对象(必须有)
method 设置期望调用的方法(必须有)
expects 设置方法调用的次数(必须有)
with 设置调用方法时的入参(可选)
will 设置调用方法后的返回值(可选)
getMock函数签名详解
getMock有7个参数,一般只需要使用第一个参数指定被mock的类即可,但是如果需要更灵活的配置mock,有必要了解其他参数:
String – Required – 需要mock的类的名称
Array – Optional – 需要mock的函数名称数组,默认情况下,会mock所有函数(即给所有函数一个空的实现),但是如果设置了需要mock的函数,那么其他函数将不会被mock,按照原来的方式执行。
Array – Optional – 需要传入给构造函数的参数,getMock方法帮你调用了构造函数,所以这里通过一个数组,给你设置构造函数参数的机会
String – Optional – 给这个mock类起一个名称,这样可以使用这个新名称创建许多同样的mock类实例。
Boolean – Optional – true将调用原始对象的构造函数,false将不掉用,默认为true
Boolean – Optional – true将可以调用原始类的clone函数,false则无法调用。
Boolean – Optional – false将禁止__autoload函数被调用,当mock对象被创建时。
匹配器(Matchers)
匹配器相当于调用mock方法的量词,作为expects函数的参数传给mock对象,用于设定期望的调用次数,主要有下面几个:
once() 期望方法只调用一次,否则测试失败
never() 期望方法从不被调用,否则测试失败
any() 期望调用任意次,测试永远不会因此失败。
at($index) 期望方法被第$indexd调用的行为,$index从0开始,一般会配合with或will使用。值得注意的是$index是针对特定mock对象而言的,而不是针对特定mock对象的特定方法。也就是说,mock对象A任意一个方法被调用一次,$index会增加1。
exactly($times) 期望执行准确的次数,否则测试失败
atLeastOnce() 期望执行至少一次,否则测试失败
约束(Constraints)
约束和with一起使用,用于设定mock函数的输入,约束有很多,主要分为一下几大类
arrayHasKey(mixed $key) 断言入参数组是否有指定的键
contains(mixed $value) 断言入参数组是否有指定的值
logicalAnd($constraint,$constraint) 断言两个参数逻辑和
logicalNot($constraint) 断言参数逻辑否
logicalOr($constraint,$constraint) 断言两个参数逻辑或
logicalXor($constraint,$constraint) 断言两个逻辑异或
matchesRegularExpression($pattern) 断言入参是否匹配正则表达式
stringContains($string, $case) 断言入参是否包含表达式
stringEndsWith( $suffix) 断言入参是否有此后缀
stringStartsWith(string $prefix) 断言入参是否有次前缀
identicalTo($value) 断言入参===当前值
equalTo($value, $delta = 0, $maxDepth = 10) 断言入菜是否==当前值
lessThan($value) 断言入参&当前值
lessThanOrEqual(mixed $value) 断言入参&=当前值
greaterThan(mixed $value) 断言入参&当前值
greaterThanOrEqual(mixed $value) 断言入参&=当前值
[类和对象]
attribute($constraint, $attributeName) 将约束赋给指定属性或对象
attributeEqualTo($attributeName, $value, $delta = 0, $maxDepth = 10) 断言value是否与当前对象的某个属性相等
classHasAttribute($attributeName) 断言当前类是否具有摸个属性
classHasStaticAttribute($attributeName) 断言当前类是否具有某个静态属性
hasAttribute($attributeName) 断言当前对象是否有指定的属性
[基本类型]
isFalse() 断言当前值为FALSE
isTrue() 断言当前对象是否为TRUE
isInstanceOf(string $className) 断言当对象是某个类的实例
isNull() 断言当前对象是否为NULL
isType($type) 断言当前对象是某个具体的类型
anything() 接受任何入参
fileExists() 断言当前入参代表的文件是否存在
设定返回值,与will一起使用,用于设定mock函数的返回值,主要方法方法如下:
returnValue($value) 返回字面意思
throwException($exception) 此方法在调用时抛出指定异常
returnArgument($index) 返回第$index个参数,从0开始
returnCallback($fun) 返回值通过回调函数生成,函数签名与被mock的函数相同
onConsecutiveCalls(arg0,arg1,…) 设定返回值列表,这样可以控制被返回值的顺序,更灵活的控制返回值,最好与匹配器any或atLeastOnce结合使用。
阅读(...) 评论()JUnit4 与 JMock 之双剑合璧
单元测试可以保证代码的质量,最大程度降低修复系统 bug 的时间和成本。能被称为测试的阶段有:单元测试、集成测试、系统测试和用户测试。修复系统 bug 的时间和成本随着这些阶段的推移呈指数级增长,特别是客户发现问题的时候,不仅是时间跟成本的损失,更是客户忠诚度的损失。由此可以看出单元测试的重要性。
JUnit 是作为 Java 开发人员单元测试的利器。据统计,目前单元测试的框架中使用最多的是 JUnit,占 35% 以上的比重。下面要介绍的是 JUnit4,是 JUnit 最新的版本。JUnit4 使用了 Java 5 注解让测试的过程变得更方便和灵活,因此备受开发者的青睐。
通常待测的类不可避免地使用其他类的方法。在不能保证其他类方法正确性的前提下,如何通过单元测试的方式保证待测试的类方法是正确的呢?或者假如待测试的方法依赖的其他类的代码还没有实现而只是定义了接口,那么待测试的方法可以测试呢? JMock 的出现解决了上面的问题。JMock 提供给开发者切断待测方法对其他类依赖的能力,使开发者能够将全部的注意力都集中于待测方法的逻辑上,而不用担心其他类方法是否能够返回正确的结果。这样的测试更具有针对性,更容易定位到潜在问题。
因此,JUnit4 与 JMock 的组合就成为 Java 开发人员写单元测试必备的利器。本文对 JUnit4 与 JMock 的组合使用、测试用例设计、常遇到的问题及可重用性方面进行了深入的探讨。JUnit4 应用
Eclipse 是 Java 开发人员非常熟悉的 IDE(集成开发环境)。目前我们选择 Eclipse 3.5 以上版本,安装配置 Sun JDK 1.5 以上版本。Eclipse 中已包含 JUnit4 的 Library,用户可以方便的导入使用。
由于在 Developerworks 上已经有许多介绍 JUnit4 应用的教程和文章,因此这里就不再赘述。对 JUnit4 还不熟悉的读者,本文推荐 作为入门教程。JMock 应用于 JUnit4 中使用 JMock,项目需要导入 JMock 相关的一系列 Jar 包。我们可以通过 得到这些 Jar 包。这样项目中就可以使用 JMock 的技术来辅助我们更好的完成单元测试了。清单 1. 依赖其他类方法的类 TestJunit4.java public class TestJunit4 {
private IM
public TestJunit4(IMathfun util){
this.util =
public int cal(int num){
return 10* util.abs(num);
我们定义了一个很简单的类,在这个类中有 cal 方法,这个方法需要调用 IMathfun 接口中的 abs 方法。已知 cal 的作用就是对其参数取绝对值,然后再乘 10 返回。那么,cal 方法依赖于接口 IMathfun 的方法 abs 完成取绝对值,我们可以通过 Mock IMathfun 实例及方法来切断对其依赖性。清单 2. 测试类 TestJunit4Test.java 1 public class TestJunit4Test extends TestCase{
private Mockery context = new JUnit4Mockery();
private IMathfun math =
private TestJunit4 test =
public void setUp() throws Exception {
super.setUp();
math = context.mock(IMathfun.class);
test = new TestJunit4(math);
context.checking(new Expectations(){
12 exactly(1).of(math).abs(-10);will(returnValue(10));
public void tearDown() throws Exception {
public void test(){
21 assertEquals(100,test.cal(-10));
上面的代码中有几个需要注意地方:1. 测试类继承了 TestCase(line1)。2. 创建了 Mockery 的对象 context(line2)。3 利用 context 对象来 mock 接口的实例(line8)及对应的方法(line12)。在这个简单的例子中我们 mock 了 math 及其方法,这样程序在运行的时候就不会去执行真正 IMathfun 实现类的代码,而转到 line12 的地方。给定数值 -10,直接返回 10。
更多关于 JMock 的知识请参阅 http://www.jmock.org/cookbook.html.用例设计与 Coverage 分析初学者在组合使用 JUnit4 和 JMock 技术写单元测试的时候,往往只能发现很少的问题甚至发现不了问题。因此,开发人员就需要一些方法和指标来保证与规范单元测试的质量。其中单元测试用例设计原则和覆盖率指标就是重要的指导原则与指标。Grenford J. Mayer 在《 The Art of Software Testing 》一书中提出:一个好的测试用例 (test case) 是指很可能找到迄今为止尚未发现的错误的测试。开发者不能只凭借自己主观或直观的想法来设计测试用例,应该要以一些比较成熟的测试用例设计方法为指导,再加上设计人员自己的经验积累才能做好用例设计。因此,也只有将用例设计方法与丰富的实践经验相融合才能设计出高质量的测试用例。
测试用例设计有三条基本指导原则:
测试用例的代表性:能够代表并覆盖各种合理的和不合理、合法的和非法的、边界的和越界的以及极限的输入数据。
测试结果的可判定性:测试执行结果的正确性是可判定的,每一个测试用例都应有相应的期望结果。
测试结果的可再现性:即对同样的测试用例,系统的执行结果应当是相同的。
写测试用例的过程也是对代码进行重新审查的过程,首先需要弄清楚待测的方法的功能是什么。其次多角度考虑这个方法该怎么写才是正确的、可靠的、高效的。再次,多考虑一些边界跟异常的情况。通常 case 的数量是由参数的个数决定的。对于每一个参数,我们需要设计三种情况对其方法进行测试,即:为 null 值,正确值和错误值。这样如果方法有 n 个参数,那么理论上 case 的数量需要 3n个。这个数量所带来的工作量是非常大的,而且也是低效的。实际工作中,我们还需要另一个指标来衡量 case 的设计是否全面,那就是覆盖率。Emma 是一个 Eclipse 的标准插件,通过这个工具我们可以得到类级别的语句覆盖率(statement coverage)和包级别的覆盖率(package coverage)。运行 Emma 后,工具会根据是否被执行将源代码行标注为不同的颜色,标记为红色的代码表示没有被执行,标记为绿色的代码表示已经被执行。我们可以通过以下步骤安装:
在 Eclipse IDE 中点击 help-&install new software.
在弹出的页面地址栏中输入:,会出现名为 EclEmma Java Code Coverage 的插件,选中并安装。安装成功后工具栏会出现一个运行 coverage 的小图标。
覆盖率是另一个用来衡量测试用例是否全面的指标。关于 coverage 还可以细分为三个更小的指标:语句覆盖率(statement coverage)、分支覆盖率(branch coverage)、以及路径覆盖率(path coverage)。图 1.三种覆盖率示例图语句覆盖率是指方法中代码行被执行的百分比。例如上图中共有 5 条语句,如果执行的步骤是 1-3-5。那么语句覆盖率是 60%。如果要提高到 100% 的话,至少需要 2 个 case 来覆盖:1-3-5 与 1-2-4-5。环境准备小节中提到的 Emma 可以提供语句覆盖率。具体执行过程:右键点击测试类 -&Coverage as-&Junit test。语句的覆盖率会在 coverage 的视图中出现,并且根据是否被执行将源代码标注成不同的颜色。分支覆盖率指的是方法中分支被执行的百分比。例如图 1 中在第一个菱形的位置处分成二个分支,在第二个菱形的位置处分成二个分支。这样共有 4 个分支。如果执行的步骤是 1-2-3-5 的话,因为只执行了其中的两个分支,所以分支覆盖率是 50%。如果要提高到 100% 的话,至少需要 2 个 case 来覆盖:1-2-3-5 与 1-F-4-5(F 第一个分支处 false)。分支的覆盖率要比语句的覆盖率更能够保证 case 的质量。目前 Emma 还不能生成分支覆盖率。Cobertura 是一个可以生成语句覆盖率跟分支覆盖率的强大工具。Cobertura 的使用比 Emma 复杂一些,需要写 ant 脚本来运行 Cobertura。利用 Cobertura 生成 html, xml 等文件来显示类的语句及分支覆盖率的情况。路径覆盖率指的是方法中路径被执行的百分比。这是一个比上面两个指标更全面的指标。路径指的是从方法的起点到终点的一条通路,如:1-2-3-5。如果想要路径的覆盖率达到 100%,那么必须要 4 个 case 才能完成:1-2-3-5,1-2-4-5,1-F-3-5,1-F-4-5。目前也有一些工具可以用来生成路径覆盖率。在测试用例设计的过程中,我们需要兼顾用例设计的指导原则与覆盖率的一些指标,再结果开发人员自身的实践经验必定能设计出好的测试用例。可能遇到的困难
组合使用 JUnit4 与 JMock 写单元测试时,通常情况下类的覆盖率难以达到 100%,源于某些方法不能直接写测试。在这一小节里,对常见的问题提供了一些解决途径。静态方法静态方法是单元测试过程中常见的困难之一。程序中通常需要调用其他的类的静态方法获取运行的数据或者参数。在这种情况下,只有程序启动以后这些参数才是存在的,而单元测试却是在程序未启动的情况下执行的。静态方法是通过类调用,而不是对象调用,因此也不能通过 JMock 的方式解决。清单 3. TestStatic.java public class TestStatic{
public TestStatic(){}
public int getOSType(){
String os = Utils.getTargetOS();
if("Windows".equals(os))
else if("Linux".equals(os)||"Unix".equals(os))
}对TestStatic类的getOSType方法写单元测试的话,由于需要调用Utils类的静态方法getTargetOS。所以,如果不做任何处理的话,单元测试是不能进行的。有两种方法可以解决这个问题。检查Utils类是否有带public修饰符类似于setTargetOS的方法。如果有并且能够通过调用的这个方法达到设置OS目的的话,我们只需要在测试方法调用此方法设置即可完成。如果上述情况不能完成。那么考虑第二种办法 - 重构TestStatic与Utils。但是,这么做会引发一些争议。为了测试而修改源代码,值得吗?这是需要开发者去权衡的问题。。对于Utils的改动很小,只需要将其方法getTargetOS的修饰符static去掉。类TestStatic的修改变化要大一些:清单 4. 修改后的 TestStatic.java public class TestStatic{
private IUtils utils =
public TestStatic(IUtils utils){
This.utils =
public int getOSType(){
String os = utils.getTargetOS();
if("Windows".equals(os))
else if("Linux".equals(os)||"Unix".equals(os))
}TestStatic.java的修该有几个地方:1. 增加了utils的成员变量。2. 修改了构造函数。3. 将类中调用外部类的静态方法改为调用非静态方法。清单 5. TestStaticTest.java public class TestStaticTest extends TestCase{
Mockery context = new JUnit4Mockery();
IUtils utils =
TestStatic stat =
public void setUp(){
utils = context.mock(IUtils.class);
Stat = new TestStatic(utils);
public void tearDown(){}
public TestOSTypeWin(){
context.checking(new Expectations(){
exactly(1).of(utils).getTargetOS();will(returnValue("Windows"));
assertEquals(0,stat.getOSType());
public TestOSTypeLN(){
context.checking(new Expectations(){
atLeast(1).of(utils).getTargetOS();
will(onConsecutiveCalls(
returnValue("Linux"),
returnValue("Unix")));
assertEquals(1,stat.getOSType());// return value:Linux
assertEquals(1,stat.getOSType());// return value:Unix
这里需要解释一下第27行,这样写的结果是:如果函数第一次被调用则返回"Linux",如果是第二次调用返回"Unix"。私有方法私有方法也是写单元测试过程中常会遇到的困难。类中的私有方法主要是供公有方法调用。测试公有方法之前需要保证私有方法的正确性。通常,开发者会在测公有方法之时测私有方法。这么做会产生一些问题,首先,为了测公有方法里的某一个私有方法,我们需要重复此私有方法调用之前的工作。其次,如果一个公有方法里调用大量私有方法时,用这种方法的写出来的测试代码会非常复杂,不利于测试。如果我们能够首先独立测试私有方法,那么就会极大地减轻公有方法的测试工作量。解决这个问题,有两种方法。
由于开发者通常会将测试类跟待测试的类置于同一包下,所以,最简单的方法是将私有方法前的修饰符修改为 protected,这样的话测试代码就可以访问原来的私有方法了。值得注意的是这样做需要修改源代码。
另一种方法不需要修改源代码,利用 Java 反射可以实现。清单 6.Data.java public class Data {
private String name = "Na";
public String getName(){
private void setName(String str){
}Data类中的setName是私有方法。我们可以通过反射的方式对其测试。清单 7. DataTest.java public class DataTest extends TestCase{
public void setUp(){
public void tearDown(){
public void test() throws Exception{
Data data = new Data();
System.out.println(data.getName());
Method m = data.getClass().getDeclaredMethod("setName", String.class);
m.setAccessible(true);
m.invoke(data, "Joh");
System.out.println(data.getName());
}清单 8. 输出结果 Na
从输出结果我们可以看出,我们通过反射调用了Data的私有方法setName,成功将其name值改变为Joh。关于Java 反射的特性,可以参阅 Java 编程思想。JMock 的一些问题
Mock concrete Object由于目前推崇面向接口(interface)的设计,Mockery 对象(context)的 mock 方法通常的参数是接口类型(context.mock(Interface.class))。但是,实际情况中我们偶然会遇到 mock 实体对象的情况。如果需要 mock 实体对象的话,跟 mock 接口有所不同,不能通过直接传实体类来构造。在 mock 实体对象之前,需要调用 context 的一个方法:setImposteriser(ClassImposteriser.INSTANCE),同时需要导入相关的三个 jar 包。
Mock 对象的方法多次调用返回不同结果
在代码清单 8 中已经给出了一个例子,对象 utils 第一次调用 getTargetOS 返回"Linux",第二次调用返回"Unix"。
Mock 对象的方法参数不能指定具体值
有些时候我们在 mock 对象的方法时,不能获取相应的参数时,解决办法是指定一个类型即可。例如:exactly(1).of(computer).getOSType(with(any(String.class)));will(returnValue(2));
如果有多个参数时,参数的匹配模式必须是一致的。也就是说要么参数都是指定类型的,要么参数都是具体值的,混合使用会由于匹配模式不一致而抛出异常。另外,数组的类型比较特别,如 String 数组的类型为 String[].class。
方法没有返回值,但是会改变其成员的值。
遇到这种情况会比较复杂,需要定义一个类去实现 Action 接口。详细见 http://www.jmock.org/custom-actions.html 。可重用性方面组合使用 JUnit4 和 JMock 写单元测试如果没有使用重用性技巧会产生大量重复性的劳动。可重用性分为两个方面:多个类的可重用性和单类的可重用性。常常会遇到一种情况:在多个测试类中都需要 mock 相同对象及其方法,我们可以将这一过程提取出来。通常测试类都继承于 TestCase,为了实现重用性,需要再定义一个类,取名为 GeneralTest,使 GeneralTest 继承 TestCase。在 GeneralTest.java 中将在多个测试类中用到的相同对象的 mock 工作封装进去。然后其他的测试类全部继承自 GeneralTest,这样测试类中就可以反复使用 GeneralTest 提供给我们的方法来 mock 对象了,我们需要做的就是简单传入几个参数而已。这样不仅能够省去大量的重复劳动,还能使测试代码看起来更简单、清晰,给我们的测试工作带来非常大的好处。在单个测试类中也可以提高可重用性。在单个测试类中也会有一些需要 mock 的对象在多个测试方法重用。可以将这些可重用的 mock 对象作为测试类的成员,将这些对象的 mock 工作置于 @Before 修饰的方法中,那么在需要用到这些对象的时候直接使用即可,不需要在每一个测试方法中重新做一遍。所带来的好处与上面一种情况是类似的。结束语对于 Java 而言,大部分开发者会使用到 JUnit4 跟 JMock 这两项技术。本文循序渐进地对 JUnit4 应用、JMock 与 JUnit4 的结合使用、用例设计、困难解决和可重用性多个阶段全面地阐述了作者在单元测试过程中的心得。在介绍的过程中,同时也会照顾一些入门级的读者,对一些操作给出了详细的步骤,并提供了大量的示例。希望入门级的读者在阅读这篇文章后对单元测试有一个全面的认识,更希望有经验的读者阅读后会有所收获。
相关主题:JMock 官方网站:JUnit 官方网站“”(developerWorks,2001 年 10 月):逐步递增测试和持续编译是极端编程方法基础的两种。把两者合并成为一个单独的、自动进行的过程 — 加上自动生成电子邮件报告 — 您就将在向 XP 梦想前进的道路上迈出坚实的步子。请跟随 Erik Hatcher,他向您展示了他是如何修改流行的 Ant 1.3 和 JUnit 测试框架,以达到让编译和测试过程完全的、用户化的自动化。“”(developerWorks,2004 年 5 月):开发人员有多种理由决定自动化单元测试。许多人甚至进一步发挥它,自动化这些测试的定位和执行。但是如果想要测试装具模块(test harness)像静态定义的那样运行呢?请跟随开发员 Michael Nadel,看看如何利用 Python 模拟静态定义的 JUnit TestSuite 类。
“”(developerWorks,2005 年 10 月):JUnit 是 Java 语言事实上的 标准单元测试库。JUnit 4 是该库三年以来最具里程碑意义的一次发布。它的新特性主要是通过采用 Java 5 中的标记(annotation)而不是利用子类、反射或命名机制来识别测试,从而简化测试。在本文中,执着的代码测试人员 Elliotte Harold 以 JUnit 4 为例,详细介绍了如何在自己的工作中使用这个新框架。注意,本文假设读者具有 JUnit 的使用经验。
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=http://www.ibm.com/developerworks/js/artrating/SITE_ID=10Zone=Java technologyArticleID=656308ArticleTitle=JUnit4 与 JMock 之双剑合璧publish-date=关注51Testing
Jest基于dva框架的单元测试最佳实践
发表于: 11:49 &作者:4 & 来源:稀土掘金
推荐标签:
  前言  以前在JavaScript项目中配置其实还是挺繁琐的,依赖各种库mocha,chai,sion或者第三方覆盖率报表生成库,但是现在推出了Jest测试框架,并在react native项目初始化时就已经集成了该环境,所以还没玩过的同学们可以耐心的看下去,说不定玩一次就爱上了写单元测试呢。  Jest框架  Jest已经内置了断言,mock方案,以及异步处理(async/await),只需简单配置即可导出代码覆盖率报告,还有针对于UI的快照测试。官方声称的Delightful JavaScript Testing  环境配置  因为是基于dva框架开发的react native项目,所以我们着重测试model类的方法(reducers和effects)  package.json中针对jest的配置"jest": {"preset": "react-native","collectCoverage": true,"coverageReporters": ["lcov"],"transformIgnorePatterns": ["node_modules/(?!react-native|react-navigation)"],"moduleNameMapper": {"react-native": "&rootDir&/mocks/react-native.js"}  collectCoverage 是否开启跑测试代码时收集覆盖率  coverageReporters 导出报告文件类型(通过该导出的文件和上传到sonar分析)  transformIgnorePatterns  transformIgnorePatterns 将一些model中涉及到的npm进行babel转换,不然在测试中无法识别es6的语法  moduleNameMapper 指定需要mock库对应的mock文件  如何写一个测试代码  首先,介绍下这个model的reducr和effect方法的功能(具体dva的model怎么写,可以github下,这里不多篇幅讲解)。reducers中的changeLoginStatus很简单就是根据payload的对象改变state中对应的key;而effects中的login方法(注:这是一个generator)就是根据请求体payload中的参数进行网络请求,这里我已经封装成一个方法了,根据返回的response来调用对应的action,从而改变state。  login.jsimport { NativeModules} from 'react-native'import { NavigationActions } from '../../utils'import quickLogin from '../../utils/userAccount'import Toast from '../../utils/Toast'import {fetchisCompletedUserInfo} from '../fill-information/server'import {fetchUserInfoAndUpdateLocal} from '../user-info/server'const {YCUserInfoPlugin,} = NativeModulesconst accountInfo = {phoneNum: ,code: 11111}export default {namespace: 'login',state: {isLogin: false,failReason: null},reducers: {changeLoginStatus(state, {payload}) {return {...state,isLogin: payload.isLogin,failReason: payload.failReason}}},effects: {* login({payload}, { call, put }) {try {const res = yield call(quickLogin, payload.phoneNum, payload.code)if (res.succeed) {yield call(YCUserInfoPlugin.setUserToken, res.data)yield put({ type: 'changeLoginStatus', payload: {isLogin: true}})} else {yield put({ type: 'changeLoginStatus', payload: {isLogin: false,failReason: 'test-failReason'}})}} catch (error) {global.log(error)}}}}  主要就是测试reducer和effect方法  login-test.jsdescribe('LoginModel------------&reducer', () =& {it('changeLoginStatus -& state all key should change to setvalue', () =& {// reduce 参数1:state初始值;参数2:actionexpect(reduces.notifyVerificatioStatus({...payload},{type: 'changeLoginStatus', payload: {isLogin: false,failReason: 'test-failReason'}})).toEqual({...payload, isLogin: false, failReason: 'test-failReason'})})})describe('LoginModel------------&effects', () =& {it('login -& login success with phone number', () =& {// Givenconst {call, put} = effectsconst saga = quickLogin.effects.loginconst actionCreator = {type: 'login',payload: {...accountInfo}}// Whenconst generator = saga(actionCreator, {call, put})generator.next()generator.next({succeed: true,data: 'Test-User-Token'})const changeLoginStatus = generator.next()const end = generator.next()// Thenexpect(changeLoginStatus.value).toEqual(put({type: 'changeLoginStatus',payload: {isLogin: true}}))expect(end.done).toEqual(true)})})  其中yield call(YCUserInfoPlugin.setUserToken, res.data)这是调用一个NativeModule方法,在执行测试的时候,你可能会发现会报找不到YCUserInfoPlugin的setUserToken方法,各位看官不急,因为这个是写在native的,我们也不需要关系它是否正确,只需知道调用了这句话即可,我们可以把它mock掉。怎么做能?  方法一:可以直接在当前测试文件,在import前执行如下代码:jest.mock('react-native', () =& {NativeModule: {YCUserInfoPlugin: {setUserToken: () =& {}}}})import ...import ...code  方法二:在创建一个名为mocks的文件夹,因为需要mock的react-native包中NativeModule对象中的YCUserInfoPlugin,所以创建创建文件为react-native.js,然后在package.json的moduleNameMapper中配置改文件的路径,即 &包名: '文件所在的路径'mocks/react-native.jsexport default const NativeModules = {YCUserInfoPlugin: {setUserToken: () =& {}}}  这样jest就知道在跑测试代码时,去找我们mock的文件了,test case 也可以顺利跑过了。因为这个中只需要知道那句代码执行就ok啦。  测试代码解析  在执行单个测试用例的时候,有可能会遇到全局设置的问题,你可以在beforeAll()或是在afterAll()周期方法中做一些初始化和回滚现场的操作。  一般来说我们主要测试数据交互的模块,所以model就是重点,正常来说我们网络请求这块是需要mock掉的,但是因为在dva框架中,我们一般把网络请求封装在effects中,而且这个方法是个generator函数(dva框架集成的redux-saga),我们可以很方面的在里面的每一个yeild语句里自定义返回值,就可以设置不同类型的返回值,来执行不同的语句覆盖。  使用体验吐槽  jest中针对于测试替身这块的能力还是没有Sinon厉害,而且API又少,文档有误导 性,想要更深入的写一些测试用例还得借助第三方的包。  Sinon介绍  当你在写测试代码中不顺利的时候,或是把其中的代码变为测试替身,绝对是一个不二选择。下面可以看下简单的测试用例,来了解下Sinon的几大概念。  person.jsexport default class Person {static say(message) {console.log('person say ', message)}static eat(food) {return `person eat ${food}`}static save(name) {console.log(`person saved -& ${name}`)}}  person-test.jsimport Person from '../person'import sinon from 'sinon'describe('sinon test', () =& {it('spy', () =& {const message = 'hello world'const spy = sinon.spy(Person, 'say')Person.say(message)expect(spy.withArgs(message).calledOnce).toEqual(true)spy.restore()})it('stub', () =& {const message = 'hello world'const returnValue = 'stub eat apple'sinon.stub(Person, 'say').callsFake((message) =& {console.log(`stub log ${message}`)})const stub = sinon.stub(Person, 'eat')stub.withArgs('apple').returns('stub eat apple')const result = Person.eat('apple')expect(stub).toEqual(returnValue)stub.restore()})it('mock', () =& {const name = 'yellow'const mock = sinon.mock(Person)mock.expects('save').once().withArgs(name)Person.save(name)mock.verify()mock.restore()})})  从上面的针对spy,stub,mock的测试用例可以很明显的看出,spy见名知义,主要是在不改变函数本身的前提下,收集函数本身的信息,如:是否被调用,调用的参数等等。  stub主要将一些有不确定因素的函数替换掉,保证返回的结果是你想要的,比如然后根据不同的返回值来覆盖不同的语句,基本上网络请求呀,呀还有一些耗时操作等.  mock这个词就很有争议啦,当你才开始写单元测试的时候,遇到一个函数中的操作不好写测试的时候,有的前辈可能就会说把它mock掉啊,然后你就去google,但是可能最后你就只是stub那个对象或是函数,就形成了很多人对mock和stub有点傻傻分不清的,我就是其中一个,啊哈哈哈哈哈。其实mock来说应该谨慎使用,因为mock可能会使对象变得很具体,具体就代表着不灵活了,对于测试用例来说这是很致命的,适用性大大降低。mock出来的对象最大的特点就是它自带断言,而且不会真正的走测试代码逻辑,然后我们在代码执行后,验证该逻辑是否是我们想要的。  有些话想要讲  相对入门级测试玩家来说Jest绝对是一大福音,环境配置简单,直接可以上手。当然,当你写的测试代码越多,你可能想要测试得更细粒度,更全面,再上手Sinon, 是一个不错的选择。最后一句有那么一点点营养的话  当写测试代码很麻烦的时候,使用测试替身,绝对是不二选择上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-7),我们将立即处理。
搜索风云榜
51Testing官方微信
51Testing官方微博
测试知识全知道}

我要回帖

更多关于 dva roadhogrc.mock 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信