요소 또는 요소 시스템을 테스트할 때는 개별적으로 테스트합니다. 예를 들어 ViewModel을 테스트하려면 에뮬레이터를 시작하고 UI를 실행할 필요가 없습니다. ViewModel은 Android 프레임워크에 종속되지 않기 때문입니다.
하지만 테스트 대상이 작동하려면 다른 항목에 종속될 수 있습니다. 예를 들어 ViewModel이 작동하려면 데이터 저장소를 사용해야 할 수 있습니다.
테스트 대상에 종속 항목을 제공해야 하는 경우 일반적으로 테스트 더블 (또는 테스트 객체)을 만드는 것이 좋습니다. 테스트 더블은 앱에서 구성요소처럼 보이고 작동하지만 특정 동작이나 데이터를 제공하기 위해 테스트에서 만들어진 객체입니다. 주요 이점은 테스트를 더 빠르고 간단하게 할 수 있다는 것입니다.
테스트 더블 유형
테스트 더블에는 다음과 같은 다양한 유형이 있습니다.
가짜
클래스의 '작동하는' 구현이 있지만 테스트에는 적합하지만 프로덕션에는 적합하지 않은 방식으로 구현된 테스트 더블입니다.
예: 인메모리 데이터베이스
가짜에는 모의 프레임워크가 필요하지 않으며 가볍습니다. 권장됩니다.
예시
프로그래밍된 대로 동작하고 상호작용에 관한 기대치를 갖는 테스트 더블입니다. 모의 항목의 상호작용이 정의된 요구사항과 일치하지 않으면 테스트가 실패합니다. 모의 항목은 일반적으로 이 모든 작업을 실행하기 위해 모의 프레임워크로 만들어집니다.
예: 데이터베이스의 메서드가 정확히 한 번 호출되었는지 확인합니다.
스텁
프로그래밍된 대로 작동하지만 상호작용에 대한 기대가 없는 테스트 더블입니다. 일반적으로 모의 프레임워크로 만듭니다. 편의를 위해 스텁보다 가짜가 선호됩니다.
가짜
전달되지만 사용되지 않는 테스트 더블입니다(예: 매개변수로 제공하기만 하면 되는 경우).
예: 클릭 콜백으로 전달된 빈 함수
스파이
실제 객체에 대한 래퍼로 모의 객체와 유사한 추가 정보도 추적합니다. 일반적으로 복잡성을 추가하지 않기 위해 피합니다. 따라서 스파이보다 가짜 또는 모의 테스트를 사용하는 것이 좋습니다.
그림자
Robolectric에서 사용되는 가짜입니다.
가짜 제품 사용의 예
UserRepository라는 인터페이스에 종속되고 첫 번째 사용자의 이름을 UI에 노출하는 ViewModel을 단위 테스트하려고 한다고 가정해 보겠습니다. 인터페이스를 구현하고 알려진 데이터를 반환하여 가짜 테스트 더블을 만들 수 있습니다.
이 가짜 UserRepository는 프로덕션 버전에서 사용할 로컬 및 원격 데이터 소스에 종속되지 않습니다. 이 파일은 테스트 소스 세트에 있으며 프로덕션 앱과 함께 제공되지 않습니다.
그림 1: 단위 테스트의 가짜 종속 항목
다음 테스트는 ViewModel이 첫 번째 사용자 이름을 뷰에 올바르게 노출하는지 확인합니다.
@TestfunviewModelA_loadsUsers_showsFirstUser(){// Given a VM using fake datavalviewModel=ViewModelA(FakeUserRepository)// Kicks off data load on init// Verify that the exposed data is correctassertEquals(viewModel.firstUserName,UserAlice.name)}
ViewModel은 테스터가 만들기 때문에 단위 테스트에서 UserRepository를 가짜로 교체하는 것은 쉽습니다. 그러나 더 큰 테스트에서는 임의의 요소를 교체하기가 어려울 수 있습니다.
구성요소 교체 및 종속 항목 삽입
테스트에서 테스트 대상 시스템의 생성을 제어할 수 없는 경우 테스트 더블의 구성요소를 대체하는 작업이 더 복잡해지고 앱의 아키텍처가 테스트 가능 설계를 따라야 합니다.
대규모 엔드 투 엔드 테스트도 테스트 더블을 사용하면 유리할 수 있습니다. 예를 들어 앱의 전체 사용자 흐름을 탐색하는 계측 UI 테스트가 여기에 해당합니다. 이 경우 테스트를 밀폐형으로 만들 수 있습니다. 격리된 테스트는 인터넷에서 데이터를 가져오는 것과 같은 모든 외부 종속 항목을 피합니다. 이렇게 하면 안정성과 성능이 개선됩니다.
그림 2: 앱의 대부분을 다루고 원격 데이터를 조작하는 대규모 테스트입니다.
이러한 유연성을 수동으로 달성하도록 앱을 설계할 수도 있지만 Hilt와 같은 종속 항목 삽입 프레임워크를 사용하여 테스트 시간에 앱의 구성요소를 교체하는 것이 좋습니다. Hilt 테스트 가이드를 참고하세요.
다음 단계
테스트 전략 페이지에서는 다양한 유형의 테스트를 사용하여 생산성을 개선하는 방법을 보여줍니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Use test doubles in Android\n\nWhen you test an element or system of elements you do it in *isolation*. For\nexample, to test a ViewModel you don't need to start an emulator and launch a UI\nbecause it doesn't (or shouldn't) depend on the Android framework.\n\nHowever, the subject under test might *depend* on others for it to work. For\ninstance, a ViewModel might depend on a data repository to work.\n\nWhen you need to provide a dependency to a subject under test, a common practice\nis to create a *test double* (or *test object*). Test doubles are objects that\nlook and act as components in your app but they're created in your test to\nprovide a specific behavior or data. The main advantages are that they make your\ntests faster and simpler.\n\nTypes of test doubles\n---------------------\n\nThere are various types of test doubles:\n\n| Fake | A test double that has a \"working\" implementation of the class, but it is implemented in a way that makes it good for tests but unsuitable for production. Example: an in-memory database. Fakes don't require a mocking framework and are lightweight. They are **preferred**. |\n| Mock | A test double that behaves how you program it to behave and that has expectations about its interactions. Mocks will fail tests if their interactions don't match the requirements that you define. Mocks are usually created with a *mocking framework* to achieve all this. Example: Verify that a method in a database was called exactly once. |\n| Stub | A test double that behaves how you program it to behave but doesn't have expectations about its interactions. Usually created with a mocking framework. Fakes are preferred over stubs for simplicity. |\n| Dummy | A test double that is passed around but not used, such as if you just need to provide it as a parameter. Example: an empty function passed as a click callback. |\n| Spy | A wrapper over a real object which also keeps track of some additional information, similar to mocks. They are usually avoided for adding complexity. Fakes or mocks are therefore preferred over spies. |\n| Shadow | Fake used in Robolectric. |\n|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n\n| **Caution:** There are conflicting definitions depending on the source. A comprehensive source is [*Mocks aren't Stubs*](https://martinfowler.com/articles/mocksArentStubs.html) by Martin Fowler.\n| **Note:** When using a library or framework, check with the authors to see if they provide any officially-supported testing infrastructures, such as fakes, that you can reliably depend on.\n\nExample using a fake\n--------------------\n\nSuppose that you want to unit test a ViewModel that depends on an interface\ncalled `UserRepository` and exposes the name of the first user to a UI. You can\ncreate a fake test double by implementing the interface and returning known\ndata. \n\n object FakeUserRepository : UserRepository {\n fun getUsers() = listOf(UserAlice, UserBob)\n }\n\n val const UserAlice = User(\"Alice\")\n val const UserBob = User(\"Bob\")\n\nThis fake `UserRepository` does not need to depend on the local and remote data\nsources that the production version would use. The file lives in the test source\nset and will not ship with the production app.\n**Figure 1**: A fake dependency in a unit test.\n\nThe following test verifies that the ViewModel correctly exposes the first user\nname to the view. \n\n @Test\n fun viewModelA_loadsUsers_showsFirstUser() {\n // Given a VM using fake data\n val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init\n\n // Verify that the exposed data is correct\n assertEquals(viewModel.firstUserName, UserAlice.name)\n }\n\nReplacing the `UserRepository` with a fake is easy in a unit test, because the\nViewModel is created by the tester. However, it can be challenging to replace\narbitrary elements in bigger tests.\n\nReplacing components and dependency injection\n---------------------------------------------\n\nWhen tests have no control over the creation of the systems under test,\nreplacing components for test doubles becomes more involved and requires the\narchitecture of your app to follow a *testable* design.\n\nEven big end-to-end tests can benefit from using test doubles, such as an\ninstrumented UI test that navigates through a full user flow in your app. In\nthat case you might want to make your test *hermetic*. A hermetic test avoids\nall external dependencies, such as fetching data from the internet. This\nimproves reliability and performance.\n**Figure 2**: A big test that covers most of the app and fakes remote data.\n\nYou can design your app to achieve this flexibility manually, but we recommend\nusing a [dependency injection](/training/dependency-injection) framework like [Hilt](/training/dependency-injection/hilt-android) to replace components\nin your app at test time. See the [Hilt testing guide.](/training/dependency-injection/hilt-testing)\n| **Note:** On Android, you can also use the [Robolectric](/training/testing/local-tests/robolectric) framework, which provides a special type of test double, called shadows.\n\nNext steps\n----------\n\nThe [Testing strategies](/training/testing/fundamentals/strategies) page shows how you can improve your productivity\nusing different types of tests."]]