0

How to get device ID in windows phone unit test?

I read this, but it didn't work for me.

In my application I am using this method, and it works in that case; but in unit test it doesn't work, failing with Exception: System.UnauthorizedAccessException: Access is denied.

Any idea about it? My related code follows:

    private static string GetClientID() {
        string id = new Guid().ToString();
        object objUniqueID;
        if(DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out objUniqueID)) {
            return ConvertEx.HexStringEncode((byte[])objUniqueID);
        }
        else {
            return "Unknown";
        }
    }
J0e3gan
  • 8,740
  • 10
  • 53
  • 80
Pavel Chehov
  • 69
  • 1
  • 8

1 Answers1

5

You shouldn't even try to get the device ID in unit tests, because the test code is not running on an actual device.

Instead, you should use an abstraction that encapsulates the retrieval of the device ID, and inject a fake implementation for testing.

For instance, write an interface like this:

public interface IDeviceIdProvider
{
    string GetDeviceId();
}

In your application, implement DeviceIdProvider like this:

class DeviceIdProvider : IDeviceIdProvider
{
    public string GetDeviceId()
    {
        object objUniqueID;
        if(DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out objUniqueID)) {
            return ConvertEx.HexStringEncode((byte[])objUniqueID);
        }
        else {
            return "Unknown";
        }
    }
}

Make every class that needs the device id depend on IDeviceIdProvider, by passing it to the constructor:

class Foo
{
    private readonly IDeviceIdProvider _deviceIdProvider;
    public Foo(IDeviceIdProvider deviceIdProvider)
    {
        _deviceIdProvider = deviceIdProvider;
    }

    public void DoSomething()
    {
        string deviceId = _deviceIdProvider.GetDeviceId();
        // do something with the device id
    }
}

...

var foo = new Foo(new DeviceIdProvider());

This is called dependency injection. You can either do it manually, or use an IoC container such as Unity, StructureMap, AutoFac, NInject, etc.

In your unit tests, create a fake implementation:

class FakeDeviceIdProvider : IDeviceIdProvider
{
    private string _deviceId = Guid.NewGuid().ToString();
    public string GetDeviceId()
    {
        return _deviceId;
    }
}

And pass it to the class you need to test, e.g. Foo in the example above:

[Test]
public void Foo_Should_Do_Something()
{
    var deviceIdProvider = new FakeDeviceIdProvider();
    var foo = new Foo(deviceIdProvider);
    // test the behavior of Foo...
}

This allows you to test Foo in isolation, independently of the real DeviceIdProvider class.

Note that instead of manually creating a fake implementation of IDeviceIdProvider, you can use a mocking library such as FakeItEasy:

[Test]
public void Foo_Should_Do_Something()
{
    var deviceIdProvider = A.Fake<IDeviceIdProvider>();
    A.CallTo(() => deviceIdProvider.GetDeviceId()).Returns("123456");
    var foo = new Foo(deviceIdProvider);
    // test the behavior of Foo...
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758