2016-02-17 15 views
5

PowerMockを使用してクラスを静的メソッドでモックしようとしていますが、具体的にはAndroid Instrumentationテスト。明確にするために、私は実際のAndroidデバイスまたはエミュレータでテストを実行したいと考えています。 Android Studio(1.5.1)とGradle(1.5.0)を使用しています。赤ちゃんを避けるために、私は本当に基本的で、むしろ原油の「こんにちは世界」アプリを作りました。このアプリは単純に2つのテキストを表示します.1つは静的メソッドから取り出され、もう1つは非静的メソッドから取得されます。私は、これら両方の「テキスト提供者」クラスの計器試験を書いています。あなたはここに、このアプリを見ることができます:Android InstrumentationテストでPowerMockとMockitoを使用する - エラー - 重複ファイル - org.mockito.plugins.MockMaker

https://github.com/Kai2k/PowerMockAndroidTest.git

計装テストを実行しようと私はそれがこのGET達成しようと多くの人々に表示されるエラーを取得:私のアプリのオン

com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK mockito-extensions/org.mockito.plugins.MockMaker 
File1: /Users/kaiarmer/.gradle/caches/modules-2/files-2.1/com.crittercism.dexmaker/dexmaker-mockito/1.4/70892a94894462c1b35df3c8a77d21b7e843550b/dexmaker-mockito-1.4.jar 
File2: /Users/kaiarmer/.gradle/caches/modules-2/files-2.1/org.powermock/powermock-api-mockito/1.6.4/fe12509b7e9e49d25131f4155145748a31e42e40/powermock-api-mockito-1.6.4.jar 

私の依存関係をbuild.gradleファイルには、次のようになります。

dependencies { 
compile fileTree(include: ['*.jar'], dir: 'libs') 
testCompile 'junit:junit:4.12' 
testCompile 'org.powermock:powermock-api-mockito:1.6.4' 
testCompile 'org.powermock:powermock-module-junit4-rule-agent:1.6.4' 
testCompile 'org.powermock:powermock-module-junit4-rule:1.6.4' 
testCompile 'org.powermock:powermock-module-junit4:1.6.4' 

androidTestCompile 'org.mockito:mockito-core:1.10.19' 
androidTestCompile 'org.powermock:powermock-api-mockito:1.6.4' 
androidTestCompile 'com.android.support:support-annotations:23.1.1' 
androidTestCompile 'com.android.support.test:runner:0.4.1' 
androidTestCompile 'com.android.support.test:rules:0.4.1' 
androidTestCompile 'org.hamcrest:hamcrest-library:1.3' 
androidTestCompile 'com.crittercism.dexmaker:dexmaker:1.4' 
androidTestCompile 'com.crittercism.dexmaker:dexmaker-mockito:1.4' 

compile 'com.android.support:appcompat-v7:23.1.1' 
compile 'com.android.support:design:23.1.1' 
} 

あなたはパワーモック上のいくつかの「testCompile」依存関係に気づくと関連しますdライブラリ(androidTestCompileに加えて)。これは、ベルトとブレースのために、ジュニット(非計装)テスト(パワーモックを使用する)も有効であるかどうかを確認したかったからです。私はこれを達成することができましたが、計測テストはできませんでした。

主な活動:

package com.example.android.powermocktest; 

import android.os.Bundle; 
import android.support.design.widget.FloatingActionButton; 
import android.support.design.widget.Snackbar; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 
import android.view.View; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.TextView; 

public class MainActivity extends AppCompatActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
    fab.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
        .setAction("Action", null).show(); 
     } 
    }); 

    TextView textView1 = (TextView)findViewById(R.id.textView1); 
    textView1.setText(GetStaticValue.getTheStaticValue()); 

    TextView textView2 = (TextView)findViewById(R.id.textView2); 
    textView2.setText(new GetNonStaticValue().getNonStaticString()); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 
} 

レイアウトファイル:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout   xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:fitsSystemWindows="true" 
tools:context="com.example.android.powermocktest.MainActivity"> 

<android.support.design.widget.AppBarLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:theme="@style/AppTheme.AppBarOverlay"> 

    <android.support.v7.widget.Toolbar 
     android:id="@+id/toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="?attr/actionBarSize" 
     android:background="?attr/colorPrimary" 
     app:popupTheme="@style/AppTheme.PopupOverlay" /> 

</android.support.design.widget.AppBarLayout> 

<include layout="@layout/content_main" /> 

<android.support.design.widget.FloatingActionButton 
    android:id="@+id/fab" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="bottom|end" 
    android:layout_margin="@dimen/fab_margin" 
    android:src="@android:drawable/ic_dialog_email" /> 

</android.support.design.widget.CoordinatorLayout> 

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:paddingBottom="@dimen/activity_vertical_margin" 
android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
app:layout_behavior="@string/appbar_scrolling_view_behavior" 
tools:context="com.example.android.powermocktest.MainActivity" 
tools:showIn="@layout/activity_main"> 

<TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/textView1" 
    android:text="Hello World!" /> 
<TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_below="@+id/textView1" 
    android:id="@+id/textView2" 
    android:text="Hello World again!" /> 
</RelativeLayout> 

と静的および非静的な値を取得するためのクラス:

package com.example.android.powermocktest; 

public class GetStaticValue { 

private final static String THE_VALUE = "Hi, I'm static"; 

public static String getTheStaticValue(){ 
    return THE_VALUE; 
} 
} 

package com.example.android.powermocktest; 

public class GetNonStaticValue { 

public String getNonStaticString(){ 
    return "Hi, I'm non-static"; 
} 
} 
ここに私の(恐ろしい)コードがあります

最後にテストクラスです。最初の計測テスト:

package com.example.android.powermocktest; 

import android.support.test.runner.AndroidJUnit4; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 

import static org.hamcrest.CoreMatchers.equalTo; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.powermock.api.mockito.PowerMockito.when; 

@RunWith(AndroidJUnit4.class) 
@PrepareForTest(GetStaticValue.class) 
public class GetStaticValueTest { 

    @Test 
    public void getStaticValueReturnsValue(){ 
     PowerMockito.mockStatic(GetStaticValue.class); 
     when(GetStaticValue.getTheStaticValue()).thenReturn("Hi, I'm static"); 
     assertThat(GetStaticValue.getTheStaticValue(), equalTo("Hi, I'm static")); 
    } 
} 

package com.example.android.powermocktest; 

import android.support.test.runner.AndroidJUnit4; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mockito; 

import static org.hamcrest.CoreMatchers.equalTo; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.mockito.Mockito.when; 

@RunWith(AndroidJUnit4.class) 
public class GetNonStaticValueTest { 

    @Test 
    public void getNonStaticValueReturnsNonStaticValue(){ 
     GetNonStaticValue getNonStaticValue = Mockito.mock(GetNonStaticValue.class); 
     when(getNonStaticValue.getNonStaticString()).thenReturn("Hi, I'm non-static"); 
     assertThat(getNonStaticValue.getNonStaticString(), equalTo("Hi, I'm non-static")); 
    } 
} 

そして今(作業)JUnitテスト:私がこれまで試した

package com.example.android.powermocktest; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

import static org.hamcrest.CoreMatchers.equalTo; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.powermock.api.mockito.PowerMockito.when; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(GetStaticValue.class) 
public class GetStaticValueTest { 

    @Test 
    public void getStaticValueReturnsValue() { 
     PowerMockito.mockStatic(GetStaticValue.class); 
     when(GetStaticValue.getTheStaticValue()).thenReturn("Hi, I'm static"); 
     assertThat(GetStaticValue.getTheStaticValue(), equalTo("Hi, I'm static")); 
    } 
} 

何:

を、私はこの問題の周りにいくつかの読書を行ってきました私が試したことのない1つの解決策は、手動でパワーモックライブラリジャーを開けて問題の重複クラスを削除することです。 (職場で)私たちはgradleを使い、地元の瓶では働かないので、私はこれをしたくないでしょう。

How to get Powermock to work with Dexmaker

私が聞いた人々は、GradleのビルドファイルのAndroidのセクションに「除外」を使用して示唆しています。これは、インストルメンテーションテストを実行するためのインストゥルメンテーションテストがapkとして(Android Studio/Gradleによって)ビルドされ、デバイス上で起動されるため、適切ではありません。そのため、テストを実行するにはパワーモックジャーが必要です。

android studio: gradle dependency error

私は、あなたが上記の私のビルドファイルに一覧表示され、依存関係の一部を削除しようとしました。たとえば、私は 'org.powermock:powermock-api-mockito'依存関係を削除しようとしましたが、例えば 'mockStatic'を使用する必要があります。

重複を除外するためにMavenを伝えることで、Mavenを使用した場合、誰かが成功したようだ:

https://groups.google.com/forum/#!searchin/powermock/android/powermock/ndZ2ZliYGCY/Eh226605u2cJ

PowerMock + Mockito + Maven on Android app showing Dex loader error

私はのGradleを伝える方法があるかどうかを確認しようとしました依存関係のjarファイル内の重複したクラスは無視しますが、これまでのところ私は失敗しています。

パワーモックは控えめに使用すると非常に便利で、2番目に、この問題は解決されていないとは信じられません(前に遭遇したことは確かです!)。最後の点として、私はグーグル自身が本質的にからかっのみ単位ではなく、計装テストのためであることを示唆しているように見えるという通知をした

http://developer.android.com/training/testing/start/index.html

誰が提供できるすべてのヘルプをいただければ幸いです。ありがとう。

+0

この問題を解決できましたか? – thedarkpassenger

+0

いいえ、まだこの問題はまだ顕著ではありません。 – Kai

答えて

0

これはプロジェクト/モジュールのgradleにはありますか?

packagingOptions { 
    exclude 'fileNameYouWantToExclude' 
} 

重複が、私は次のようにこの問題を回避することができました

+0

私の問題は、いくつかのジャーのクラスが重複していることです。私はその瓶の中に他のクラスが必要なので、瓶全体を取り除く(または除外する)ことはできません。現在のところ、解決策は実行可能な解決策ではない多くのjarハッキングであると思われます。誰かが重複授業を無視するように成績を伝える方法を知っていなければ? – Kai

2

を発見された場合は、この方法ではAndrodは、1つのファイルだけを配置します。 APK [ファイル名]にコピーされた重複ファイルというエラーメッセージが表示された場合は、[ファイル名]をpackagingOptionsで除外するように追加します。

android { 
    packagingOptions { 
     exclude 'mockito-extensions/org.mockito.plugins.MockMaker' 
    } 
} 
+0

私は上記の除外を使用していますが、今はテストが見つかりませんでした。 –

+0

これはテストをロードする際にエラーが発生し、私にとってはうまくいかない – Miquel

関連する問題