2017-11-27 11 views
1

테스트 커버리지를받는 방법을 설명해 주시겠습니까? 나는 모키토가 완전히 반 직관적이기 때문에 도움을 찾고있다. 모의 객체만을 사용한다면 어떻게 테스트 커버리지를 얻을 수 있습니까? 나는 이해하지 못한다.Android 용 Mockito로 테스트하기

내 테스트는 다음과 같습니다.

package dev.game.adventure; 


import static junit.framework.Assert.assertEquals; 
import static junit.framework.Assert.assertTrue; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.CoreMatchers.*; 
import static org.mockito.Mockito.*; 

import android.content.Context; 
import android.content.res.Resources; 
import android.graphics.drawable.Drawable; 
import android.widget.TextView; 

import org.junit.Ignore; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mock; 
import org.mockito.runners.MockitoJUnitRunner; 

@RunWith(MockitoJUnitRunner.class) 
public class AdventureTest { 

    private static final String FAKE_STRING = "HELLO WORLD"; 

    @Mock 
    Simulation engine; 

    @Mock 
    AdventureWorld mWorld; 

    @Mock 
    Adventure mworld; 

    @Mock 
    Context aContext; 

    @Mock 
    FullscreenActivity mActivity; 

    @Mock 
    Drawable mDrawable; 

    @Mock 
    Resources mResources; 

    @Mock 
    Place mPlace; 

    @Mock 
    AdventureGame ag; 


    @Test 
    @Ignore 
    public void Tedye() { 
     //when(mWorld.defaultPlace()).thenReturn(mPlace); 
     // myObjectUnderTest.wakeMeAfter(new WalkingPerson(myObjectUnderTest, mWorld, "new", 2, mActivity), 10); 
     //String result2 = myObjectUnderTest.getHelloWorldString(); 
     //assertThat(result2, is(FAKE_STRING));} createPlace("Heaven", target, R.mipmap.dungeon2); 
     // Adventure a = new Adventure(textview, mactivity, ag); 

    } 


    @Test 
    @Ignore 
    public void testd() { 
//   Textview scrollable = ''''''''''''(R.id.textView1); 

     when(mWorld.defaultPlace()).thenReturn(mPlace); 
     Context mCont; 

    } 


    @Test 
    @Ignore 
    public void adventureWorld() { 
     // Simulation myObjecUnderTest = new Simulation(); 
     Adventure a = new Adventure(new TextView(aContext), mActivity, ag); 
     Player p = a.getPlayer(); 
     p.say("foobar", mActivity); 
     p.say("Hello my name is " + a.getPlayer().getMe().name, mActivity); 

    } 
    //@Ignore 
    @Test 
    public void adventureTest() { 
     Simulation myObjectUnderTest = new Simulation(); 
     when(mWorld.defaultPlace()).thenReturn(mPlace); 
     myObjectUnderTest.wakeMeAfter(new WalkingPerson(myObjectUnderTest, mWorld, "new", 2, mActivity), 10); 
     String result2 = myObjectUnderTest.getHelloWorldString(); 
     assertThat(result2, is(FAKE_STRING)); 
    } 
    //@Ignore 
    @Test 
    public void personTest() { 
     Simulation myObjectUnderTest = new Simulation(); 
     when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     when(mActivity.getResources()).thenReturn(mResources); 
     when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     when(mWorld.defaultPlace()).thenReturn(mPlace); 
     WalkingPerson myObjectUnderTest2 = new WalkingPerson(myObjectUnderTest, mWorld, "blaha", 2, mActivity); 
     String result2 = myObjectUnderTest2.getHelloWorldString(); 
     myObjectUnderTest2.getThings(); 
     myObjectUnderTest2.getWorld(); 
     assertThat(result2, is(FAKE_STRING)); 
    } 
    //@Ignore 
    @Test 
    public void trollTest() { 
     Simulation myObjectUnderTest = new Simulation(); 
     AdventureWorld ag; 
     when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     when(mActivity.getResources()).thenReturn(mResources); 
     when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     when(mWorld.defaultPlace()).thenReturn(mPlace); 
     WalkingPerson myObjectUnderTest2 = new Troll(myObjectUnderTest, mWorld, "Loki", mActivity); 
     String result2 = myObjectUnderTest2.getHelloWorldString(); 
     myObjectUnderTest2.getThings(); 
     AdventureWorld adv = (AdventureWorld) myObjectUnderTest2.getWorld(); 
     //assertThat(adv.defaultPlace().toString().equals(mWorld.defaultPlace().toString())); 
     // assertThat(adv.defaultPlace(), is(FAKE_STRING)); 
     assertThat(myObjectUnderTest2.getName(), is("Loki")); 
     //assertThat(adv.messsage, is(FAKE_STRING)); 
    } 
    //@Ignore 
    @Test 
    public void cokeTest() { 
     when(mWorld.getPlace("Dungeon")).thenReturn(mPlace); 
     mWorld.getPlace("Dungeon").addThing(new CocaCola("Ljummen cola")); 
     Simulation myObjectUnderTest = new Simulation(); 
     when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     when(mActivity.getResources()).thenReturn(mResources); 
     when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     when(mWorld.defaultPlace()).thenReturn(mPlace); 
     WalkingPerson myObjectUnderTest2 = new Troll(myObjectUnderTest, mWorld, "blaha", mActivity); 
     String result2 = myObjectUnderTest2.getHelloWorldString(); 
     myObjectUnderTest2.getThings(); 
     myObjectUnderTest2.getWorld(); 
     assertThat(result2, is(FAKE_STRING)); 
    } 
    @Ignore 
    @Test 
    public void testPlace() { 
     Simulation myObjectUnderTest = new Simulation(); 
     when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable); 
     mWorld.createPlace("Heaven", mActivity, R.mipmap.dungeon2); 
     mWorld.createPlace("Hell", mActivity, R.mipmap.dungeon2); 
     mWorld.connect("Heaven", "Hell", "Down", "Up"); 
     mWorld.randomPlace(); 
     assertTrue(false); 

    } 
    @Ignore 
    @Test 
    public void useAppContext() throws Exception { 
     // Context of the app under test. 
     // Context appContext = InstrumentationRegistry.getTargetContext(); 
     // assertEquals("dev.game.adventure", appContext.getPackageName()); 
    } 
} 

저장소는 available online입니다.

+0

하나의 접근법은 테스트중인 실제 코드를 사용하여 쉽게 테스트 할 수없는 상황을 테스트하기 위해 모의 (mocks)를 선택적으로 사용하는 것입니다. 예를 들어,'Whatever' 클래스에'something()'메소드가있어'Swot' 객체를 포함하지 않는'Frobozz' 인스턴스를 반환 할 수 있습니다 만, 이것을 할 수있는'Whatever'을 쉽게 생성 할 수 없습니다 (윤년에만 비가 내리기 때문에). 그래서, 여러분은'something()'을 모의 (mock)로 만들어 테스트를 위해이 특정 결과를 리턴하고, 평소와 달리'Whatever'을 테스트합니다. – CommonsWare

+0

나는 어리 석고 나는 이해하지 못한다. 모의 객체를 사용할 때 나는 0 % 코드 커버리지를 얻는다. –

+0

* 조롱당한 물건이 0 % 적용됩니다. 특정 상태의 객체가 필요한 다른 코드 *를 테스트하기위한 모의 객체를 만들고 모의 객체는 그러한 객체를 얻는 가장 간단한 방법입니다. 또는 모의 객체를 만들어 해당 모의 객체에서 다른 코드 호출 메소드의 결과를 기록합니다. 모의의 목표는 * 다른 코드 *에 대한 테스트를 작성하고 다른 코드의 적용 범위를 향상시키는 데 도움을주는 것입니다. – CommonsWare

답변

1

단위 테스트에 도움을주기 위해 모의 (mock)를 적용하는 방법에 대한 간단한 예를 썼습니다. 잘하면이 일을 명확히하는 데 도움이 될 수 있습니다. 이 예에서

, 나는 아이디어가 SampleClass이 작업을 수행하는 데 도움이 Validator의 인스턴스에 의존 인 상태 SampleClassValidator라는 두 가지 기본 클래스가 있습니다.

SampleClass :

//This class's only function is to return one string if the username it's given is valid, and another string if its not valid. It does this with the help of the Validator class 

public class SampleClass { 

    private final Validator validator; 

    public SampleClass(Validator v){ 
     this.validator = v; 
    } 

    public String createWelcomeMessage(final String username){ 

     if(this.validator.isValid(username)){ 
      return "Welcome, " + username + "!"; 
     } 

     return username + " is not a valid username."; 

    } 

} 

검사기 :

//This class's only job is to validate strings. Right now, all it does is check the length, and fail if its > 15 characters. 
public class Validator { 

    public boolean isValid(final String str) { 

     if(str.length() > 15){ 
      return false; 
     } 

     return true; 
    } 

} 

이 그래서 내가 SampleClass에 대한 몇 가지 단위 테스트를 작성하고 싶은 말은하자. 단위 테스트는 일반적으로 작고 집중된 코드 단위를 테스트해야하며 Validator의 특정 세부 정보가 이러한 테스트에 유출되는 것을 원하지 않습니다. Validator 클래스의 출력이 SampleClass에 미치는 영향과 SampleClass이 구현하는 기능에 대해 신경을 써야합니다. 과 같은 상호 조롱 (및 모키토)이 있습니다. SampleClass의 동작을 테스트하기 위해 Validator과의 상호 작용을 조롱 할 수 있습니다.

SampleClassTest : 단위 테스트 커버리지를보고 jacoco를 사용

public class SampleClassTest { 

    //Mock the validator class, which SampleClass depends on. 
    private Validator validator = Mockito.mock(Validator.class); 

    //Do not mock the SampleClass class. Create a new one, and use the mocked validator within it. 
    private SampleClass sampleClass = new SampleClass(validator); 


    //Test that a valid username will print out the message "Welcome, username!" 
    @Test 
    public void testValidUsername(){ 

     Mockito.when(validator.isValid(Mockito.anyString())).thenReturn(true); 
     final String message = this.sampleClass.createWelcomeMessage("testuser"); 

     Assert.assertEquals("Welcome, testuser!", message); 

    } 


    //Test that an invalid username will print out the message "username is not a valid username" 
    @Test 
    public void testInvalidUsername(){ 

     Mockito.when(validator.isValid(Mockito.anyString())).thenReturn(false); 

     final String message = this.sampleClass.createWelcomeMessage("thisiswaywaywaytoolong"); 
     Assert.assertEquals("thisiswaywaywaytoolong is not a valid username.", message); 
    } 

} 

, SampleClass이 완전히 덮여 있으며, 지금은 조롱과 검증되지 않은 있기 때문에 Validator가 완전히 발견된다. 나는 고립 된 단위 테스트를 Validator (unmocked!)에 작성해야한다.

enter image description here

프로젝트에 적용 :

를 예를 들어, go method on your Person class을 고려하십시오. 이 메서드에 대한 단위 테스트를 작성하고 FullscreenActivityWorld 개체에 Mocks를 사용하고 메서드가 다양한 조건에서 World 개체를 올바르게 조작하는지 확인하십시오. 일부 단위 테스트에서는 Person->go을 커버하므로 Person 테스트가 다른 클래스와 분리되어있는 방식으로 테스트해야합니다. 이것은 또한 복잡한 위젯 또는 비 실용적인 클래스를 테스트하는 대신 Android 위젯 등을 (CommonsWare에서 언급 한 것처럼) 처리 할 때 매우 유용 할 수 있습니다.

TL; DR

  • 사용 특정 유닛 테스트의 초점되지 않은 다른 클래스/개체 모의 종속성 조롱. 특히 복잡하거나 실용적이지 클래스는/당신은하지 사용 망신 시켰습니다,하지만 대신에, 당신은 당신이 unmocked 클래스에 대한 단위 테스트를 작성하기 위해 모의 객체를 사용해야한다
  • (CommonsWare 정말 코멘트에 잘 설명)
객체