Window Phone 的 TestAccelerometer 实现

TestAccelerometer implementation for Window Phone

问题

我的应用程序通过 Microsoft.Devices.Sensors.Accelerometer class

使用加速度计数据

现在我想编写 Unit 或 CodedUI 测试,因此我需要有一个特殊的测试实现 Accelerometer 来控制返回的数据

理论上我有3个选择:

  1. 创建 Accelerometer 的子 class - 不可能,因为 Accelerometersealed class
  2. 通过在 run-time 处使用反射替换 Accelerometer 的实现 - 恕我直言,这不是最佳选择
  3. 创建 SensorBase<AccelerometerReading> 的子class - 不错的选择

我决定按照 #1 并将我的 TestAccelerometer 实施为 SensorBase<AccelerometerReading>child

这是我的问题:

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

错误很明显我查看了反编译代码(JetBrains dotPeak 工具),但根本没有找到任何构造函数。

问题

如何找到合适的构造函数用于我的 TestAccelerometer 实现?

反编译代码

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();
  }
}

找到了构造函数:

internal SensorBase();

此构造函数阻止 SensorBase 具有默认的 public 构造函数,并且此 class 无法从其程序集外部进行子class。

测试它会很复杂。您可以重新设计应用程序并使用 wrapper/adapter 作为 Accelerometer 仅用于测试目的,或者您可以检查 Windows [=25= 上是否存在 mocking a sealed class 的可能性].