2

我可以在真实设备上使用基本 Activity 生成 Spec 对象。但是,通过 Robolectric 在 JVM 下使用 Android SDK 时,我无法重现 Spec 对象。我需要在 Robolectric 单元测试中增加什么来复制与真实设备相同的行为?

以下是适用于真实设备的代码。

package net.lapasa.testkeypairgeneratorspec;

import android.os.Bundle;
import android.security.KeyPairGeneratorSpec;
import android.support.v7.app.AppCompatActivity;

import java.math.BigInteger;
import java.util.Calendar;

import javax.security.auth.x500.X500Principal;

public class MainActivity extends AppCompatActivity
{

    private static final String TEST_ALIAS = "TEST_ALIAS";
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        KeyPairGeneratorSpec.Builder builder = new KeyPairGeneratorSpec.Builder(this); //mock(KeyPairGeneratorSpec.Builder.class);
        KeyPairGeneratorSpec spec = getSpec(builder); // THIS WORK, NOT NULL

    }

    private KeyPairGeneratorSpec getSpec(KeyPairGeneratorSpec.Builder builder)
    {
        Calendar notBefore = Calendar.getInstance();
        Calendar notAfter = Calendar.getInstance();
        notAfter.add(Calendar.YEAR, 1);

        String alias = TEST_ALIAS;
        builder.setAlias(alias);
        builder.setSubject(new X500Principal(String.format("CN=%s, OU=%s", alias, getPackageName())));
        builder.setSerialNumber(BigInteger.ONE);
        builder.setStartDate(notBefore.getTime());
        builder.setEndDate(notAfter.getTime());
        KeyPairGeneratorSpec spec = builder.build();

        return spec;

    }


}

但是,当尝试在 Robolectric 单元测试中复制此行为时,它无法返回 Spec 对象:

package net.lapasa.testkeypairgeneratorspec;

import android.security.KeyPairGeneratorSpec;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

import java.math.BigInteger;
import java.security.Security;
import java.util.Calendar;

import javax.security.auth.x500.X500Principal;

import static org.junit.Assert.assertNotNull;

@RunWith(RobolectricTestRunner.class)
public class SpecGenerationTest
{
    public SpecGenerationTest()
    {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    private KeyPairGeneratorSpec getSpec(KeyPairGeneratorSpec.Builder builder)
    {
        Calendar notBefore = Calendar.getInstance();
        Calendar notAfter = Calendar.getInstance();
        notAfter.add(Calendar.YEAR, 1);

        String alias = "Test Alias";
        builder.setAlias(alias);
        builder.setSubject(new X500Principal(String.format("CN=%s, OU=%s", alias, RuntimeEnvironment.application.getPackageName())));
        builder.setSerialNumber(BigInteger.ONE);
        builder.setStartDate(notBefore.getTime());
        builder.setEndDate(notAfter.getTime());
        KeyPairGeneratorSpec spec = builder.build();

        return spec;
    }

    @Test
    public void testGenerateSpec() throws Exception
    {
        KeyPairGeneratorSpec.Builder builder = new KeyPairGeneratorSpec.Builder(RuntimeEnvironment.application);
        KeyPairGeneratorSpec spec = getSpec(builder);

        assertNotNull(spec); // THIS DOESN'T WORK, WHY IS IT NULL?
    }
}

更新:这是我尝试创建自定义阴影的尝试,但它仍然返回 null。我不确定参数是否实际设置在 -REAL OBJECT-

package shadow.net.lapasa.testkeypairgeneratorspec;

import android.content.Context;
import android.security.KeyPairGeneratorSpec;

import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.internal.Shadow;

import java.math.BigInteger;
import java.util.Date;

import javax.security.auth.x500.X500Principal;

@Implements(KeyPairGeneratorSpec.Builder.class)
public class ShadowKeyPairGeneratorSpecBuilder
{
    @RealObject
    private KeyPairGeneratorSpec.Builder builder;


    private Context context;
    private X500Principal subject;
    private BigInteger serialNumber;
    private Date startDate;
    private Date endDate;
    private String alias;

    public void __constructor__(Context context)
    {
        this.context = context;
    }


    /**
     * Sets the alias to be used to retrieve the key later from a KeyStore instance using the AndroidKeyStore provider.
     *
     * @param alias
     */
    @Implementation
    public void setAlias(String alias)
    {
        this.alias = alias;
        Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class).setAlias(alias);

    }

    /**
     * Sets the subject used for the self-signed certificate of the generated key pair.
     *
     * @param subject
     */
    @Implementation
    public void setSubject(X500Principal subject)
    {
        this.subject = subject;
        Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class).setSubject(subject);
    }


    /**
     * Sets the serial number used for the self-signed certificate of the generated key pair.
     *
     * @param serialNumber
     */
    @Implementation
    public void setSerialNumber(BigInteger serialNumber)
    {
        this.serialNumber = serialNumber;
        Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class).setSerialNumber(serialNumber);
    }


    /**
     * Sets the start of the validity period for the self-signed certificate of the generated key pair.
     *
     * @param startDate
     */
    @Implementation
    public void setStartDate(Date startDate)
    {
        this.startDate = startDate;
        Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class).setStartDate(startDate);
    }

    /**
     * Sets the subject used for the self-signed certificate of the generated key pair.
     *
     * @param endDate
     */
    @Implementation
    public void setEndDate(Date endDate)
    {
        this.endDate = endDate;
        Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class).setEndDate(endDate);
    }

    @Implementation
    public KeyPairGeneratorSpec build()
    {
//        KeyPairGeneratorSpec spec = Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class, "build", null);
        KeyPairGeneratorSpec spec = builder.setAlias(alias).setSubject(subject).setSerialNumber(serialNumber).setStartDate(startDate).setEndDate(endDate).build();
//        KeyPairGeneratorSpec spec = Shadow.directlyOn(builder, KeyPairGeneratorSpec.Builder.class).build();
        return spec; // Cannot instantiate KeyPairGeneratorSpec directly because it's not available publically. It can only be generated through KeyPairGeneratorSpec.Builder generator
    }
}
4

0 回答 0