Xamarin单元测试便携式诱饵和开关错误与Xamarin.Auth?

时间:2017-09-04 18:04:58

标签: xamarin xamarin.ios xamarin.forms

我在Visual Studio for Mac中设置了一个TestProject,它引用了我的Xamarin Forms项目来测试代码的非可视部分。

但是当我尝试测试一段利用Xamarin.Auth访问钥匙串的代码时,我收到以下错误。

System.NotImplementedException : 
Portable Bait And Switch is nuget feature, so the package must be installed in all project.

NotImplementedException will indicate that Portable Code from PCL is used and not Platform Specific
implementation. Please check whether platform specific Assembly is properly installed.

Cannot save account in Portable profile - bait-and-switch error.
Please file a bug in https://bugzilla.xamarin.com

此代码在iOS模拟器上运行良好,我认为它与xamarin auth利用ios Keychain的方式有关,而ios Keychain在此测试项目中不存在。我试图在引用中添加我的ios解决方案,但我无法在我的测试项目的“编辑引用”中这样做。项目引用对话框不允许它:enter image description here

以下是我的PCL中失败的代码。

 AccountStore store;
 store = AccountStore.Create();

显然,它在AccountStore.Create()

方面遇到了问题

以下是调用PCL的testcode类:

using System;
using NUnit.Framework;
using CrowdWisdom;
using CrowdWisdom.Authentication;

namespace CrowdWisdomTest
{
    [TestFixture()]
    public class AuthServiceTest
    {
        [Test()]
        public void SaveRestoreSecret()
        {
            String secret = "ABCD";
            AuthService auth = AuthService.GetInstance();
            auth.putSecret("MySecret", secret);
            Assert.AreEqual(secret, auth.GetSecret("MySecret"));
    }
  }
}

2 个答案:

答案 0 :(得分:3)

大多数跨平台插件使用的诱饵和开关模式 - 不是一个非常单元测试的友好模式。正如您在示例中看到的那样。

我的第一个建议是使用基于合同的方法,以及依赖注入容器用于授权过程;这样您就可以提供模拟实现作为单元测试上下文。但是,如果这是不可能的,那么您可以使用以下hack为这些静态类提供自己的模拟开关。

基本上,您看到的错误是因为您的可移植代码正在访问Xamarin.Auth的便携版本,而该版本只是诱饵。因此,您必须创建自己的实现,以充当单元测试上下文中的切换(正如他们在Xamarin.Auth中的平台特定库中所做的那样)。

为此,您需要:

  1. 创建另一个可移植库(仅供您的单元测试项目使用)。假设我们将其命名为Xamarin.Auth.Mocks。确保在其属性页面中将根命名空间和程序集名称更新为“Xamarin.Auth”。

    enter image description here

  2. 添加模拟帐户商店类,并使用切换模式实现AccountStore

    namespace Xamarin.Auth
    {
        /// <summary>
        /// A persistent storage for <see cref="Account"/>s. This storage is encrypted.
        /// Accounts are stored using a service ID and the username of the account
        /// as a primary key.
        /// </summary>
    #if XAMARIN_AUTH_INTERNAL
        internal abstract partial class AccountStore
    #else
        public abstract partial class AccountStore
    #endif
        {
            public static AccountStore Create()
            {
                return new MockAccountStore();
            }
        }
    
        public class MockAccountStore : AccountStore
        {
    
        }
    }
    
  3. 在您的单元测试库中添加对Xamarin.Auth.Mocks的引用

  4. 现在,每次运行单元测试时,您的可移植代码都会找到满足Xamarin.Auth所有需求的模拟开关实现,并实现与Xamarin.Auth的真正隔离;从技术上来说,当我们编写单元测试时,我们仍然渴望这样做。

    注意: 如果您的可移植代码使用其他诱饵开关类,请在Xamarin.Auth.Mocks库中为它们添加模拟实现。您只需要为代码中使用的类添加模拟类;并非Xamarin.Auth

    中的所有课程

答案 1 :(得分:0)

我遇到了同样的问题,在我的情况下,所有项目中的Xamarin.Auth版本都是相同的(1.7.0)。 我通过以这种方式编辑.csproj解决了该问题:

<Reference Include="Xamarin.Auth, Version=1.6.0.1, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\..\packages\Xamarin.Auth.1.7.0\lib\MonoAndroid10\Xamarin.Auth.dll</HintPath>
      <Private>True</Private>
</Reference>

添加标签<Private>True</Private>为我解决了此问题。 该引用必须存在,并且在.csproj文件中带有此标记。