Search code examples
c#windows-phone-8decompiling

TestAccelerometer implementation for Window Phone


Problem

My application use accelerometer data via Microsoft.Devices.Sensors.Accelerometer class

Now I wanna write Unit or CodedUI tests, for this reason I need to have a special test implementation of Accelerometer to controlling returned data

In theory I have 3 options:

  1. Create subclass of Accelerometer - impossible because Accelerometer is sealed class
  2. By using reflection replace implementation of Accelerometer at run-time - isn't best option IMHO
  3. Create subclass of SensorBase<AccelerometerReading> - good option

I have decided to go by #1 and implement my TestAccelerometer as child of SensorBase<AccelerometerReading>

And here is I have problem:

`Error  CS1729  'SensorBase<AccelerometerReading>' does not contain a constructor that takes 0 arguments`

Error pretty clear I have looked in decompiled code (JetBrains dotPeak tool) and don't found any constructors at all.

Questions

How can I found proper constructor to use in my TestAccelerometer implementation?

Decompiled code

Microsoft.Devices.Sensors.Accelerometer

// Type: Microsoft.Devices.Sensors.Accelerometer
// Assembly: Microsoft.Devices.Sensors, Version=8.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e
// MVID: 81ED89AA-6B11-4B39-BAFA-38D59CBB1E3B
// Assembly location: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\WindowsPhone\v8.0\Microsoft.Devices.Sensors.dll

using System;

namespace Microsoft.Devices.Sensors
{
  /// <summary>
  /// Provides Windows Phone applications access to the device’s accelerometer sensor.
  /// </summary>
  public sealed class Accelerometer : SensorBase<AccelerometerReading>
  {
    /// <summary>
    /// Gets or sets whether the device on which the application is running supports the accelerometer sensor.
    /// </summary>
    /// 
    /// <returns>
    /// true if the device on which the application is running supports the accelerometer sensor; otherwise, false.
    /// </returns>
    public static bool IsSupported { get; internal set; }

    /// <summary>
    /// Gets the current state of the accelerometer. The value is a member of the <see cref="T:Microsoft.Devices.Sensors.SensorState"/> enumeration.
    /// </summary>
    /// 
    /// <returns>
    /// Type: <see cref="T:Microsoft.Devices.Sensors.SensorState"/>.
    /// </returns>
    public SensorState State { get; private set; }

    /// <summary>
    /// Occurs when new data arrives from the accelerometer. This method is deprecated in the current release. Applications should use the <see cref="E:Microsoft.Devices.Sensors.SensorBase`1.CurrentValueChanged"/> event of the <see cref="T:Microsoft.Devices.Sensors.SensorBase`1"/> class instead.
    /// </summary>
    [Obsolete("use CurrentValueChanged")]
    public event EventHandler<AccelerometerReadingEventArgs> ReadingChanged;

    static Accelerometer();

    /// <summary>
    /// Releases the managed and unmanaged resources used by the <see cref="T:Microsoft.Devices.Sensors.Accelerometer"/>.
    /// </summary>
    public new void Dispose();

    /// <summary>
    /// Starts data acquisition from the accelerometer.
    /// </summary>
    public new void Start();

    /// <summary>
    /// Stops data acquisition from the accelerometer.
    /// </summary>
    public new void Stop();
  }
}

Microsoft.Devices.Sensors.SensorBase

// Type: Microsoft.Devices.Sensors.SensorBase`1
// Assembly: Microsoft.Devices.Sensors, Version=8.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e
// MVID: 81ED89AA-6B11-4B39-BAFA-38D59CBB1E3B
// Assembly location: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\WindowsPhone\v8.0\Microsoft.Devices.Sensors.dll

using System;
using System.Security;

namespace Microsoft.Devices.Sensors
{
  /// <summary>
  /// The base class for all Windows Phone sensor classes.
  /// </summary>
  /// <typeparam name="TSensorReading">The type of reading returned by the sensor.</typeparam>
  public abstract class SensorBase<TSensorReading> : IDisposable where TSensorReading : ISensorReading
  {
    /// <summary>
    /// Gets an object that implements <see cref="T:Microsoft.Devices.Sensors.ISensorReading"/> that contains the current value of the sensor. This object will be one of the following types, depending on which sensor is being referenced: <see cref="T:Microsoft.Devices.Sensors.AccelerometerReading"/>, <see cref="T:Microsoft.Devices.Sensors.CompassReading"/>, <see cref="T:Microsoft.Devices.Sensors.GyroscopeReading"/>, <see cref="T:Microsoft.Devices.Sensors.MotionReading"/>.
    /// </summary>
    /// 
    /// <returns>
    /// An object that implements <see cref="T:Microsoft.Devices.Sensors.ISensorReading"/> that contains the current value of the sensor.
    /// </returns>
    public TSensorReading CurrentValue { get; }

    /// <summary>
    /// Gets or sets the preferred time between <see cref="E:Microsoft.Devices.Sensors.SensorBase`1.CurrentValueChanged"/> events.
    /// </summary>
    /// 
    /// <returns>
    /// Type: <see cref="T:System.TimeSpan"/>. The preferred time between CurrentValueChanged events.
    /// </returns>
    public TimeSpan TimeBetweenUpdates { get; set; }

    /// <summary>
    /// Gets the validity of the sensor’s data.
    /// </summary>
    /// 
    /// <returns>
    /// Type: <see cref="T:System.Boolean"/>. true if the sensor’s data is valid; otherwise, false.
    /// </returns>
    public bool IsDataValid { get; }

    /// <summary>
    /// Occurs when new data arrives from the sensor.
    /// </summary>
    public event EventHandler<SensorReadingEventArgs<TSensorReading>> CurrentValueChanged;

    static SensorBase();

    internal SensorBase();

    /// <summary>
    /// Allows an object to try to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection.
    /// </summary>
    [SecuritySafeCritical]
    ~SensorBase();

    /// <summary>
    /// Releases the managed and unmanaged resources used by the sensor.
    /// </summary>
    [SecuritySafeCritical]
    public void Dispose();

    /// <summary>
    /// Starts acquisition of data from the sensor.
    /// </summary>
    public virtual void Start();

    /// <summary>
    /// Stops acquisition of data from the sensor.
    /// </summary>
    public virtual void Stop();
  }
}

Solution

  • You did find a constructor:

    internal SensorBase();
    

    This constructor prevents the SensorBase from having a default public constructor and this class cannot be subclassed from outside its assembly.

    Testing it will be complicated. You could redesign the app and use a wrapper/adapter for the Accelerometer just for the puropse of testing or you could check if there's a possibility of mocking a sealed class on Windows Phone.