rainit2006 / Android-

记录一下Android基本知识
0 stars 0 forks source link

有用的工具/验证工具 #11

Open rainit2006 opened 7 years ago

rainit2006 commented 7 years ago

Andorid的单元测试介绍系列 https://zhuanlan.zhihu.com/p/25882260 https://zhuanlan.zhihu.com/p/25882966 https://zhuanlan.zhihu.com/p/25936894 https://zhuanlan.zhihu.com/p/25982343 https://zhuanlan.zhihu.com/p/26030341 http://chriszou.com/2016/05/10/android-unit-testing-di-dagger.html

rainit2006 commented 7 years ago
rainit2006 commented 7 years ago

image

和JUnit3的不同点: image

rainit2006 commented 7 years ago

image

image

image

image

rainit2006 commented 7 years ago

Mock以及Mockito https://zhuanlan.zhihu.com/p/25982343

所谓的mock就是创建一个类的虚假的对象,在测试环境中,用来替换掉真实的对象,以达到两大目的: 1,验证这个对象的某些方法的调用情况,调用了多少次,参数是什么等等 2,指定这个对象的某些方法的行为,返回特定的值,或者是执行特定的动作 要使用Mock,一般需要用到mock框架,这篇文章我们使用Mockito这个框架

使用Mockito,验证一个对象的方法调用情况的姿势是: Mockito.verify(objectToVerify).methodToVerify(arguments); 其中,objectToVerify和methodToVerify分别是你想要验证的对象和方法。

如果你想验证一个对象的某个方法得到了多次调用,只需要将次数传给Mockito.times()就好了。 Mockito.verify(mockUserManager, Mockito.times(3)).performLogin(...); //验证mockUserManager的performLogin函数得到了三次调用。

很多时候你并不关心被调用方法的参数具体是什么,或者是你也不知道,你只关心这个方法得到调用了就行。这种情况下,Mockito提供了一系列的any方法,来表示任何的参数都行: Mockito.verify(mockUserManager).performLogin(Mockito.anyString(), Mockito.anyString()); anyString()表示任何一个字符串都可以。null?也可以的! 类似anyString,还有anyInt, anyLong, anyDouble等等。anyObject表示任何对象,any(clazz)表示任何属于clazz的对象。

另外, 指定mock对象的某个方法,让它返回特定值的写法如下: Mockito.when(mockObject.targetMethod(args)).thenReturn(desiredReturnValue);

//当调用mockValidator的verifyPassword方法时,返回true,无论参数是什么 Mockito.when(validator.verifyPassword(anyString())).thenReturn(true);

函数里包含callback时的验证方法: 这种指定mock对象执行特定的动作的写法如下: Mockito.doAnswer(desiredAnswer).when(mockObject).targetMethod(args); 传给doAnswer()的是一个Answer对象(callback),我们想要执行什么样的动作,就在这里面实现。


Mockito.doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        //这里可以获得传给performLogin的参数
        Object[] arguments = invocation.getArguments();

        //callback是第三个参数
        NetworkCallback callback = (NetworkCallback) arguments[2];

        callback.onFailure(500, "Server error");
        return 500;
    }
}).when(mockUserManager).performLogin(anyString(), anyString(), any(NetworkCallback.class));

当然,使用Mockito.doAnswer()需要创建一个Answer对象,这有点麻烦,代码看起来也繁琐,如果想简单的指定目标方法“什么都不做”,那么可以使用Mockito.doNothing()。如果想指定目标方法“抛出一个异常”,那么可以使用Mockito.doThrow(desiredException)。如果你想让目标方法调用真实的逻辑,可以使用Mockito.doCallRealMethod()。

SampleA をテスト対象のクラスにします。

public class SampleA {
    private SampleC sampleC;

    public String createName() {
        Integer id = sampleC.getId();

        Integer price = sampleC.getPrice(id);

        String ret = "id:" + id + " price:" + price;
        return ret;
    }
}

SampleC のクラス

public class SampleC {

    public  Integer getId() {
            return 1 + 2;
    }

    public  Integer getPrice(Integer id) {
        Integer price = id * 100;
        return price;
    }
}

@Spyを使って、SampleAのテストをします。

import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
public class MockitoSampleTest {

    @Spy
    private SampleC sampleCMock = new SampleC();

    @InjectMocks
    private SampleA sampleA = new SampleA();

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testVerify() {

        // モックを用意する。
        // getPrice()メソッドのみをモック化します。
        doReturn(555).when(sampleCMock).getPrice((Integer)anyObject());

        // テスト対象のクラスを実行します。
        String ret = sampleA.createName();

        // 戻り値を確認する。
        assertEquals("id:3 price:555", ret);
    }
}

サンプルソースでは、 getPrice()メソッドは、モック化しています。 getId()メソッドは、モック化していません。

rainit2006 commented 7 years ago

Dagger2

LoginActivity所需要的,不过是一个LoginPresenter而已,然而它却需要知道LoginPresenter的Dependency是什么,LoginPresenter的Dependency的Dependency又是什么,然后new一堆东西出来。而且可以预见的是,这个app的其他地方也需要这里的OkHttpClient、Retrofit、SharedPreference、UserManager等等dependency,因此也需要new这些东西出来,造成大量的代码重复,和不必要的object instance生成。 如果能达到这样的效果,那该有多好:我们只需要在一个类似于dependency工厂的地方统一生产这些dependency,以及这些dependency的dependency。所有需要用到这些Dependency的client都从这个工厂里面去获取。而且更妙的是,一个client(比如说LoginActivity)只需要知道它直接用到的Dependency(LoginPresenter),而不需要知道它的Dependency(LoginPresenter)又用到哪些Dependency(UserManager和PasswordValidator)。系统自动识别出这个依赖关系,从工厂里面把需要的Dependency找到,然后把这个client所需要的Dependency创建出来。

在dagger2里面,负责生产这些Dependency的统一工厂叫做 Module ,所有的client最终是要从module里面获取Dependency的,然而他们不是直接向module要的,而是有一个专门的“工厂管理员”,负责接收client的要求,然后到Module里面去找到相应的Dependency,提供给client们。这个“工厂管理员”叫做 Component。基本上,这是dagger2里面最重要的两个概念。

link.zhihu.com/?target=http%3A//chriszou.com/2016/05/10/android-unit-testing-di-dagger.html

rainit2006 commented 7 years ago

image

rainit2006 commented 6 years ago

Live2D http://sites.cybernoids.jp/cubism2/beginner-tutorial/08/beginner-tutorial

Google Guava Googleが開発しているOSSのjava core libraryで、Googleの多くのJavaベースのプロジェクトで使用されており、 Java 1.5 以上で使用できる。 Apache Commons の Lang、Collectionsなどに替わる機能を提供していて、パッケージ名を見れば大体の機能について想像がつくと思います。 com.google.common.annotations com.google.common.base com.google.common.cache com.google.common.collect com.google.common.escape com.google.common.eventbus com.google.common.hash com.google.common.html com.google.common.io com.google.common.math com.google.common.net com.google.common.primitives com.google.common.reflect com.google.common.util.concurrent

ToSpeakG3 音声合成ミドルウェア. https://toshiba.semicon-storage.com/jp/product/software-ip/tospeak.html