本文介绍了如何嘲笑一个单元测试的Andr​​oid NFC Tag对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前工作的一个Android项目,需要NFC集成。现在我想写一些(J)单元测试,看是否应用程序能够接收NFC意图(特别是 ACTION_TECH_DISCOVERED ),并把给定的标记(在 NfcAdapter.EXTRA_TAG )的总线系统上。但让我吃惊,我不能创建一个标签实例或模拟之一。谁能向我解释如何我可以(单位)测试?

I'm currently working on an Android project which needs NFC integration. Now I want to write some (j)unit tests to see if the application can receive NFC intents (specifically ACTION_TECH_DISCOVERED) and put the given tag (in NfcAdapter.EXTRA_TAG) on a bus system. However to my surprise I cannot create a Tag instance or mock one. Can someone explain to me how I can (unit) test?

在这一点上,我甚至会接受集成测试的一种形式,过程:

At this point I would even accept a form of integration testing, the process of:


  1. 检测NFC意图

  2. 获得标签对象

  3. 把它包在 CardDetectedEvent
  4. 总线上
  1. Detect the NFC Intent
  2. Get the Tag object
  3. Put it on the bus wrapped in a CardDetectedEvent.

我有一个手机的NFC和一些卡进行测试。

I have a phone with NFC enabled and a few cards for testing.

Android的SDK版本:19

图书馆使用:robolectric,JUnit和的Mockito

Android SDK version: 19
Libraries used: robolectric, junit and mockito

推荐答案

这是可能使用反射来创建一个模拟标记对象实例(注意,这是不公开的Andr​​oid SDK的一部分,所以它可能无法为未来的Andr​​oid版本)

It's possible to create a mock tag object instance using reflection (note that this is not part of the public Android SDK, so it might fail for future Android versions).


  1. 获得 createMockTag()方法虽然反映:

Class tagClass = Tag.class;
Method createMockTagMethod = tagClass.getMethod("createMockTag", byte[].class, int[].class, Bundle[].class);


  • 为$ P $一些常量pparing模拟标记的实例:

  • Define some constants for preparing the mock tag instance:

    final int TECH_NFC_A = 1;
    final String EXTRA_NFC_A_SAK = "sak";    // short (SAK byte value)
    final String EXTRA_NFC_A_ATQA = "atqa";  // byte[2] (ATQA value)
    
    final int TECH_NFC_B = 2;
    final String EXTRA_NFC_B_APPDATA = "appdata";    // byte[] (Application Data bytes from ATQB/SENSB_RES)
    final String EXTRA_NFC_B_PROTINFO = "protinfo";  // byte[] (Protocol Info bytes from ATQB/SENSB_RES)
    
    final int TECH_ISO_DEP = 3;
    final String EXTRA_ISO_DEP_HI_LAYER_RESP = "hiresp";  // byte[] (null for NfcA)
    final String EXTRA_ISO_DEP_HIST_BYTES = "histbytes";  // byte[] (null for NfcB)
    
    final int TECH_NFC_F = 4;
    final String EXTRA_NFC_F_SC = "systemcode";  // byte[] (system code)
    final String EXTRA_NFC_F_PMM = "pmm";        // byte[] (manufacturer bytes)
    
    final int TECH_NFC_V = 5;
    final String EXTRA_NFC_V_RESP_FLAGS = "respflags";  // byte (Response Flag)
    final String EXTRA_NFC_V_DSFID = "dsfid";           // byte (DSF ID)
    
    final int TECH_NDEF = 6;
    final String EXTRA_NDEF_MSG = "ndefmsg";              // NdefMessage (Parcelable)
    final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";  // int (result for getMaxSize())
    final String EXTRA_NDEF_CARDSTATE = "ndefcardstate";  // int (1: read-only, 2: read/write, 3: unknown)
    final String EXTRA_NDEF_TYPE = "ndeftype";            // int (1: T1T, 2: T2T, 3: T3T, 4: T4T, 101: MF Classic, 102: ICODE)
    
    final int TECH_NDEF_FORMATABLE = 7;
    
    final int TECH_MIFARE_CLASSIC = 8;
    
    final int TECH_MIFARE_ULTRALIGHT = 9;
    final String EXTRA_MIFARE_ULTRALIGHT_IS_UL_C = "isulc";  // boolean (true: Ultralight C)
    
    final int TECH_NFC_BARCODE = 10;
    final String EXTRA_NFC_BARCODE_BARCODE_TYPE = "barcodetype";  // int (1: Kovio/ThinFilm)
    


  • 为您的变量类型中技术含量的额外包。例如,对于一个NFC-A与NDEF消息标记:

  • Create the tech-extras bundle for your tag type. For instance, for an NFC-A tag with an NDEF message:

    Bundle nfcaBundle = new Bundle();
    nfcaBundle.putByteArray(EXTRA_NFC_A_ATQA, new byte[]{ (byte)0x44, (byte)0x00 }); //ATQA for Type 2 tag
    nfcaBundle.putShort(EXTRA_NFC_A_SAK , (short)0x00); //SAK for Type 2 tag
    
    Bundle ndefBundle = new Bundle();
    ndefBundle.putInt(EXTRA_NDEF_MAXLENGTH, 48); // maximum message length: 48 bytes
    ndefBundle.putInt(EXTRA_NDEF_CARDSTATE, 1); // read-only
    ndefBundle.putInt(EXTRA_NDEF_TYPE, 2); // Type 2 tag
    NdefMessage myNdefMessage = ...; // create an NDEF message
    ndefBundle.putParcelable(EXTRA_NDEF_MSG, myNdefMessage);  // add an NDEF message
    


  • prepare您标签的防碰撞识别/ UID(见 Tag.getId()方法)。例如。 7字节UID为2类标签:

  • Prepare an anti-collision identifier/UID for your tag (see Tag.getId() method). E.g. a 7-byte-UID for a Type 2 tag:

    byte[] tagId = new byte[] { (byte)0x3F, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, (byte)0x90, (byte)0xAB };
    


  • 然后就可以通过调用 createMockTag()方法创建一个模拟标记实例

  • Then you can create a mock tag instance by invoking the createMockTag() method

    Tag mockTag = (Tag)createMockTagMethod.invoke(null,
            tagId,                                     // tag UID/anti-collision identifier (see Tag.getId() method)
            new int[] { TECH_NFC_A, TECH_NDEF },       // tech-list
            new Bundle[] { nfcaBundle, ndefBundle });  // array of tech-extra bundles, each entry maps to an entry in the tech-list
    


  • 一旦你创建了一个模拟标记对象,你可以把它作为一个NFC发现意图的一部分。例如。为 TECH_DISCOVERED 目的:

    Once you created that mock tag object, you can send it as part of an NFC discovery intent. E.g. for a TECH_DISCOVERED intent:

    Intent techIntent = new Intent(NfcAdapter.ACTION_TECH_DISCOVERED);
    techIntent.putExtra(NfcAdapter.EXTRA_ID, tagId);
    techIntent.putExtra(NfcAdapter.EXTRA_TAG, mockTag);
    techIntent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[]{ myNdefMessage });  // optionally add an NDEF message
    

    您可以发送这个意图您的活动:

    You can then send this intent to your activity:

    techIntent.setComponent(...); // or equivalent to optionally set an explicit receiver
    startActivity(techIntent);
    

    接收器甚至可以使用模拟标记对象来检索技术类的实例。然而,需要IO操作的任何方法都将失败。

    The receiver can even use the mock tag object to retrieve instances of the technology classes. However, any method that requires IO operations will fail.

    这篇关于如何嘲笑一个单元测试的Andr​​oid NFC Tag对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    07-31 16:58