领域单元测试

编程入门 行业动态 更新时间:2024-10-22 16:24:39
本文介绍了领域单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试对Realm及其交互进行单元测试,但进展并不顺利.我已经包含了所有依赖项,并不断出现模糊的故障,下面是Helper类的代码,该类是Realm的包装.

I am trying to unit test Realm and its interactions but things are not going too well. I have included all dependencies and keep getting vague failures, below is my code for the Helper class which is a wrapper over Realm.

问题

  • 这是测试Realm的正确方法吗?

  • Is this the correct way of testing Realm?

    我如何测试应用程序沙箱中的数据,只能通过UI/仪器测试来测试这些数据?

    How can I test data that is in the app's sandbox, can that data only be tested by UI/Instrumentation tests?

    当前(如下),并且在得到"Powermock零参数构造函数不存在"之前,我得到一个错误.

    I am getting an error currently (below) and before I was getting a "Powermock zero args constructor doesn't exist"

    GitHub存储库

    以下是我用于单元测试的当前代码:

    Below is the current code I have for my Unit test:

    @RunWith(PowerMockRunner.class) @PowerMockRunnerDelegate(RobolectricTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21, application = CustomApplicationTest.class) @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "javax.crypto.","java.security.*"}) @SuppressStaticInitializationFor("io.realm.internal.Util") @PrepareForTest({Realm.class, RealmConfiguration.class, RealmQuery.class, RealmResults.class, RealmCore.class, RealmLog.class}) public class DatabaseHelperTest { @Rule public PowerMockRule rule = new PowerMockRule(); private DatabaseHelper dB; private Realm realmMock; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mockStatic(Realm.class); mockStatic(RealmConfiguration.class); mockStatic(RealmCore.class); mock(DatabaseHelper.class); final Realm mockRealm = PowerMockito.mock(Realm.class); realmMock = mockRealm; final RealmConfiguration mockRealmConfig = PowerMockito.mock(RealmConfiguration.class); doNothing().when(RealmCore.class); RealmCore.loadLibrary(any(Context.class)); whenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig); when(Realm.getInstance(any(RealmConfiguration.class))).thenReturn(mockRealm); when(Realm.getDefaultInstance()).thenReturn(mockRealm); when(Realm.getDefaultInstance()).thenReturn(realmMock); when(realmMock.createObject(Person.class)).thenReturn(new Person()); Person person = new Person(); person.setId("2"); person.setName("Jerry"); person.setAge("25"); Person person2 = new Person(); person.setId("3"); person.setName("Tom"); person.setAge("22"); List<Person> personsList = new ArrayList<>(); personsList.add(person); personsList.add(person2); RealmQuery<Person> personRealmQuery = mockRealmQuery(); when(realmMock.where(Person.class)).thenReturn(personRealmQuery); RealmResults<Person> personRealmResults = mockRealmResults(); when(realmMock.where(Person.class).findAll()).thenReturn(personRealmResults); when(personRealmResults.iterator()).thenReturn(personsList.iterator()); when(personRealmResults.size()).thenReturn(personsList.size()); when(realmMock.copyFromRealm(personRealmResults)).thenReturn(personsList); realmMock = mockRealm; dB = new DatabaseHelper(realmMock); } @Test public void insertingPerson(){ doCallRealMethod().when(realmMock).executeTransaction(any(Realm.Transaction.class)); Person person = mock(Person.class); when(realmMock.createObject(Person.class)).thenReturn(person); dB.putPersonData(); verify(realmMock, times(1)).createObject(Person.class); verify(person, times(1)).setId(anyString()); } @Test public void testExistingData(){ List<Person> personList = dB.getPersonList(); //NPE if checking person object properties i.e name, id. Only list size is available why? Assert.assertEquals(2, personList.size()); } @SuppressWarnings("unchecked") private <T extends RealmObject> RealmQuery<T> mockRealmQuery() { return mock(RealmQuery.class); } @SuppressWarnings("unchecked") private <T extends RealmObject> RealmResults<T> mockRealmResults() { return mock(RealmResults.class); }

    错误:

    org.mockito.exceptions.misusing.NotAMockException: Argument passed to verify() is of type Realm$$EnhancerByMockitoWithCGLIB$$317bc746 and is not a mock! Make sure you place the parenthesis correctly! See the examples of correct verifications: verify(mock).someMethod(); verify(mock, times(10)).someMethod(); verify(mock, atLeastOnce()).someMethod(); at com.appstronomy.realmunittesting.db.DatabaseHelperTest.insertingPerson(DatabaseHelperTest.java:133) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    推荐答案

    这是测试Realm的正确方法吗?

    Is this the correct way of testing Realm?

    如何进行官方测试.而仪器测试似乎很简单,单元测试相当复杂:

    How about following the official tests. While instrumentation tests seem easy, unit test are quite involved:

    @RunWith(PowerMockRunner.class) @PowerMockRunnerDelegate(RobolectricTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21) @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"}) @SuppressStaticInitializationFor("io.realm.internal.Util") @PrepareForTest({Realm.class, RealmConfiguration.class, RealmQuery.class, RealmResults.class, RealmCore.class, RealmLog.class}) public class ExampleActivityTest { // Robolectric, Using Power Mock github/robolectric/robolectric/wiki/Using-PowerMock @Rule public PowerMockRule rule = new PowerMockRule(); private Realm mockRealm; private RealmResults<Person> people; @Before public void setup() throws Exception { // Setup Realm to be mocked. The order of these matters mockStatic(RealmCore.class); mockStatic(RealmLog.class); mockStatic(Realm.class); mockStatic(RealmConfiguration.class); Realm.init(RuntimeEnvironment.application); // Create the mock final Realm mockRealm = mock(Realm.class); final RealmConfiguration mockRealmConfig = mock(RealmConfiguration.class); // TODO: Better solution would be just mock the RealmConfiguration.Builder class. But it seems there is some // problems for powermock to mock it (static inner class). We just mock the RealmCore.loadLibrary(Context) which // will be called by RealmConfiguration.Builder's constructor. doNothing().when(RealmCore.class); RealmCore.loadLibrary(any(Context.class)); // TODO: Mock the RealmConfiguration's constructor. If the RealmConfiguration.Builder.build can be mocked, this // is not necessary anymore. whenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig); // Anytime getInstance is called with any configuration, then return the mockRealm when(Realm.getDefaultInstance()).thenReturn(mockRealm); // Anytime we ask Realm to create a Person, return a new instance. when(mockRealm.createObject(Person.class)).thenReturn(new Person()); // Set up some naive stubs Person p1 = new Person(); p1.setAge(14); p1.setName("John Young"); Person p2 = new Person(); p2.setAge(89); p2.setName("John Senior"); Person p3 = new Person(); p3.setAge(27); p3.setName("Jane"); Person p4 = new Person(); p4.setAge(42); p4.setName("Robert"); List<Person> personList = Arrays.asList(p1, p2, p3, p4); // Create a mock RealmQuery RealmQuery<Person> personQuery = mockRealmQuery(); // When the RealmQuery performs findFirst, return the first record in the list. when(personQuery.findFirst()).thenReturn(personList.get(0)); // When the where clause is called on the Realm, return the mock query. when(mockRealm.where(Person.class)).thenReturn(personQuery); // When the RealmQuery is filtered on any string and any integer, return the person query when(personQuery.equalTo(anyString(), anyInt())).thenReturn(personQuery); // RealmResults is final, must mock static and also place this in the PrepareForTest annotation array. mockStatic(RealmResults.class); // Create a mock RealmResults RealmResults<Person> people = mockRealmResults(); // When we ask Realm for all of the Person instances, return the mock RealmResults when(mockRealm.where(Person.class).findAll()).thenReturn(people); // When a between query is performed with any string as the field and any int as the // value, then return the personQuery itself when(personQuery.between(anyString(), anyInt(), anyInt())).thenReturn(personQuery); // When a beginsWith clause is performed with any string field and any string value // return the same person query when(personQuery.beginsWith(anyString(), anyString())).thenReturn(personQuery); // When we ask the RealmQuery for all of the Person objects, return the mock RealmResults when(personQuery.findAll()).thenReturn(people); // The for(...) loop in Java needs an iterator, so we're giving it one that has items, // since the mock RealmResults does not provide an implementation. Therefore, anytime // anyone asks for the RealmResults Iterator, give them a functioning iterator from the // ArrayList of Persons we created above. This will allow the loop to execute. when(people.iterator()).thenReturn(personList.iterator()); // Return the size of the mock list. when(people.size()).thenReturn(personList.size()); this.mockRealm = mockRealm; this.people = people; } @Test public void shouldBeAbleToAccessActivityAndVerifyRealmInteractions() { doCallRealMethod().when(mockRealm).executeTransaction(Mockito.any(Realm.Transaction.class)); // Create activity ExampleActivity activity = Robolectric.buildActivity(ExampleActivity.class).create().start().resume().visible().get(); assertThat(activity.getTitle().toString(), is("Unit Test Example")); // Verify that two Realm.getInstance() calls took place. verifyStatic(times(2)); Realm.getDefaultInstance(); // verify that we have four begin and commit transaction calls // Do not verify partial mock invocation count: github/jayway/powermock/issues/649 //verify(mockRealm, times(4)).executeTransaction(Mockito.any(Realm.Transaction.class)); // Click the clean up button activity.findViewById(R.id.clean_up).performClick(); // Verify that begin and commit transaction were called (been called a total of 5 times now) // Do not verify partial mock invocation count: github/jayway/powermock/issues/649 //verify(mockRealm, times(5)).executeTransaction(Mockito.any(Realm.Transaction.class)); // Verify that we queried for Person instances five times in this run (2 in basicCrud(), // 2 in complexQuery() and 1 in the button click) verify(mockRealm, times(5)).where(Person.class); // Verify that the delete method was called. Delete is also called in the start of the // activity to ensure we start with a clean db. verify(mockRealm, times(2)).delete(Person.class); // Call the destroy method so we can verify that the .close() method was called (below) activity.onDestroy(); // Verify that the realm got closed 2 separate times. Once in the AsyncTask, once // in onDestroy verify(mockRealm, times(2)).close(); }

    上级答案

    medium/@q2ad/android-testing-realm -2dc1e1c94ee1 有一个很好的建议:不要模拟Realm,而要使用一个临时实例.带有依赖项注入的原始命题:使用

    medium/@q2ad/android-testing-realm-2dc1e1c94ee1 has a great proposal: do not mock Realm, but use a temporary instance instead. Original proposition with dependency injection: Use

    RealmConfiguration testConfig = new RealmConfiguration.Builder(). inMemory(). name("test-realm").build(); Realm testRealm = Realm.getInstance(testConfig);

    如果无法进行依赖注入,则可以使用

    Realm.setDefaultConfiguration(testConfig);

    而是设置Realm.getDefaultInstance()返回的Realm.

    如果收到java.lang.IllegalStateException,请记住事先调用Realm.init(InstrumentationRegistry.getTargetContext()),并将文件放在android-test目录中. (即:使用仪器测试,而不是单元测试).

    If you receive a java.lang.IllegalStateException, remember to call Realm.init(InstrumentationRegistry.getTargetContext()) beforehand, and put the files inside the android-test directory. (that is: use an instrumentation test, not a unit test).

  • 更多推荐

    领域单元测试

    本文发布于:2023-11-14 19:25:29,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1588327.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:单元测试   领域

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!